Thread: Ignoring most information from File.

  1. #16
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    It looks like to me that all you need to do is parse line by line and look in between the pipe characters (|) for tokens. The strcspn() function makes tasks like that easy. Since the function returns the number of characters before a pipe was found, you can print or copy a string of exactly the right length. Try this in a loop:
    Code:
            tokenLength = strcspn(string, "|\n");
            printf("\t%.*s\n", (int)tokenLength, string);
    With some pointer arithmetic, you can get it done in a few more lines. You need to skip the delimiter (++string; ) and know when you've reached the end of the line you are parsing.

    Also note that ignoring input is basically reading input that you never used. You are going to have to slog through data that you don't need to get to what you do need. Count columns to realize where you are in relation to something useful on each line of data.

    I don't think magically slapping on wide characters is going to make the output look better, if that is still a problem. If the file is ANSI encoded there is no point in putting in more difficult code when a change of the command prompt window code page would make the output look correct. Does the OP even know the file's encoding?
    Last edited by whiteflags; 12-28-2014 at 11:10 PM.

  2. #17
    Registered User
    Join Date
    Jun 2014
    Posts
    79
    @WhiteFlags

    Incredible! I have been having that strcspn() function in front of my eyes litterally for YEARS and I NEVER ever noticed it! And I can't say how many times I read the standard library reference (millions?). Many thanks for your hint, WhiteFlags. I'm sure it will be useful to me soon.

  3. #18
    Registered User
    Join Date
    Dec 2014
    Location
    Czech Republic
    Posts
    36
    I didn't notice that there is another post, so I did what helped me aldo_baldo.

    Code:
        for(int i = 0; fgets(radek, 50, mena) != NULL; ++i){        if(i > 1){
                char *data = radek;
                char *dataPtrs[ukoncovaciZnak];
                for(dataPtrs[0] = data, i = 1; i < ukoncovaciZnak; ++i){
                    dataPtrs[i] = strchr(dataPtrs[i-1], '|')+1;
                }
                for(int i = 0; data[i] != '\0'; ++i){
                    if(data[i] == '|' || data[i] == '\n')
                        data[i] = '\n';
                }
                for(int i = 0; data[i] != '\0'; ++i){
                    if(data[i] == ',')
                       data[i] = '.';
                }
    
    
              //  printf("%s", data);
                sscanf(data, "%s %s %d %s %f", zeme, menaC, &mnozstvi, kod, &kurz);
                printf("%d %s = %.3f\n", mnozstvi, kod, kurz);
            }
        }
    Output:Ignoring most information from File.-ds-png

    But where was in title space it to copyed the same line.

  4. #19
    Registered User
    Join Date
    Jun 2014
    Posts
    79
    With the following, you are putting extra '\n' newline characters instead of extra terminators '\0'. That way, you are not going to divide the single "data" string into substrings, just making the single "data" string a multiline one.

    Code:
    for(int i = 0; data[i] != '\0'; ++i){
        if(data[i] == '|' || data[i] == '\n')
            data[i] = '\n'; /* you should use '\0' terminators here,
                               or the trick is not going to work */
    }
    Once you are done with '\0' in place of each '|' and '\n' previously in the "data" string, you can treat each pointer in dataPtrs[] as an independent string. Completely remove the sscanf() call and try using printf() directly with dataPtrs[0], dataPtrs[1], dataPtrs[2], dataPtrs[3] and/or dataPtrs[4] according to your needs. As an example, try something like this:

    Code:
    printf( "%s\n", dataPtrs[3] ); /* this is going to print the
                                      name of your second currency */
    If needed, you can even convert the numeric values found in dataPtrs[2] and in dataPtrs[4] to a data type you find convenient. As an example, try something like this:

    Code:
    double rate;
    rate = atof( dataPtrs[4] ); /* this is going to convert the substring
                                   pointed to by dataPtrs[4] into the equivalent
                                   double value (stored in "rate"; you can then
                                   use the double variable as needed */
    Remember: once you have your dataPtrs[] pointers set and your '|' and '\n' characters changed with '\0' terminators, you can treat each dataPtrs[] pointer as an actual, independent string.

  5. #20
    Registered User
    Join Date
    Dec 2014
    Location
    Czech Republic
    Posts
    36
    Thx very much.

    It's working, but didn't how i imagine :/.

    Code:
      FILE *mena;    mena = fopen("mena.txt", "r");
    
    
        if(mena == NULL){
            printf("Error: soubor nebyl nalezen.\nPokud soubor existuje: prejmenujejte jej na mena.txt.\n");
            return 1;
        }
    
    
        char radek[50], *kod, kodStatu[4];
        float suma, kurz, meziVysl=0, vysl=0;
        int mnozstvi;
    
    
       //prevod(suma);
    
    
    
    
        for(int i = 0; fgets(radek, 50, mena) != NULL; ++i){
            if(i > 1){
                char *data = radek;
                char *dataPtrs[ukoncovaciZnak];
                for(dataPtrs[0] = data, i = 1; i < ukoncovaciZnak; ++i){
                    dataPtrs[i] = strchr(dataPtrs[i-1], '|')+1;
                }
                for(int i = 0; data[i] != '\0'; ++i){
                    if(data[i] == '|' || data[i] == '\n')
                       data[i] = '\0';
                    if(data[i] == ',')
                       data[i] = '.';
                }
    
    
                kurz = atof(dataPtrs[4]);
                mnozstvi = atol(dataPtrs[2]);
                kod = dataPtrs[3];
    
    
                printf("%4ld %s = %.3f\n", mnozstvi , kod, kurz);    //<- there working fine
            }
        }
        puts("\n");
    
    
        printf("%4ld %s = %.3f\n", mnozstvi , kod, kurz); //<- behind the cycle not, only last line
    
    
        fclose(mena);
    I need working with them.

    User write kod=code (example EUR) suma=sum (5.00)
    then write code on what he want convert price for example AUD, so 5EUR = 7.40AUD

    but when i writed this:
    Code:
    void prevod(float suma){    printf("Kolik si prejete prevest: ");
        scanf("%f", &suma);
        if(suma < 0){
            printf("Zadali jste zapornou hodnotu.\n");
        }else printf("Suma: %.3f", suma);
    }
    //-----  in main(void) to cycle
    
    prevod(suma);  // uncountable cycling and when i writed behind the cycle, in kurz, mnozstvi, kod was only last line

  6. #21
    Registered User
    Join Date
    Jun 2014
    Posts
    79
    Siggi, sadly I must admit that the language you are using for your variables and for your user interface doesn't help me to understand the requirements of the program you are writing. Keep in mind that I'm and Italian guy who's reading/writing in (poor) English, and that I have no idea of what sentences like "Pokud soubor existuje" mean (of course I try to guess, but guessing is not a good communication technique, I fear).

    Indeed, I'm enjoying what we are doing here a lot, but I'm stuck and can't go on in an efficient way unless you use plain/basic English. Or Italian, if you prefer.

    Dai, che è divertente! (Come on, it's fun!)

    Anyway, if I got it right, the problem you are trying to solve has a rather simple solution via the strcmp() or strncmp() standard functions from the string.h include file. One should get the relevant data while parsing the data file, store them in a couple of proper variable, break out of the cicle and show the solution to the user.

    Waiting for your code in a language that we can share (English, I bet).
    Last edited by aldo_baldo; 12-30-2014 at 03:38 AM.

  7. #22
    Registered User
    Join Date
    Dec 2014
    Location
    Czech Republic
    Posts
    36
    This is my code for now. Tryed translate to english.

    Code:
    #include <stdio.h>#include <stdlib.h>
    #include <string.h>
    
    
    #define endingChar 5
    
    
    void convert(float summ){
        printf("\nHow much do you want convert: ");
        scanf("%f", &summ);
        if(summ < 0){
            printf("Error: negative number.\n");
        }else printf("Summ: %.3f", summ);
    }
    
    
    int main(void)
    {
        //printf("Dom. ukol c.4.\n");
    
    
        FILE *mena;
        mena = fopen("mena.txt", "r");
    
    
        if(mena == NULL){
            printf("Error: file wasn't found.\nIf exist: rename on mena.txt.\n");
            return 1;
        }
    
    
        char line[50], *code, codeState[4], instruction; //rod[50]; testing what it did
        float summ=0, exchangeRate, meziResult=0, result=0;
        int quantity;
    
    
    
    
    start:
        convert(summ);
        printf("\nDefault currency: ");
        scanf("%3s", codeState);
    
    
        for(int i = 0; fgets(line, 50, mena) != NULL; ++i){
            if(i > 1){
                char *data = line;
                char *dataPtrs[endingChar];
                for(dataPtrs[0] = data, i = 1; i < endingChar; ++i){
                    dataPtrs[i] = strchr(dataPtrs[i-1], '|')+1;
                }
                for(int i = 0; data[i] != '\0'; ++i){
                    if(data[i] == '|' || data[i] == '\n')
                       data[i] = '\0';
                    if(data[i] == ',')
                       data[i] = '.';
                }
    
    
                exchangeRate = atof(dataPtrs[4]);
                quantity = atol(dataPtrs[2]);
                code = dataPtrs[3];
    
    
               printf("%4ld %s = %.3f\n", quantity , code, exchangeRate);
                 if(strcmp(code, codeState) == NULL){ //only working if is exactly in form, but i want testing upper and lowercase, it must working same if i'll get codeState = gbP or GBP or Gbp
            *rod = kod[i]; // testing what it do
        }
            }
        }
        puts("\n");
    
    
        printf("%4ld %s = %.3f\n", quantity , code, exchangeRate);
        printf("***%s***", rod); // doing wierd things
    
    
    
    
    
    
    operation:
        printf("\nContinue typing: a/n\n");
        scanf("%c", &instruction);
        scanf("%c", &instruction);
    
    
        switch(instruction){
            case 'n': case 'N':{
                goto end;
            }
            case 'a': case 'A':{
                goto start;
            }
            default:{
                printf("Negative opration.\n\n");
                goto operation;
            }
        }
    end:
    
    
        fclose(mena);
    
    
        puts("\nEnd programm.");
        return 0;
    }
    I'm thinking about it but don't know how it realize. I try it explain.

    I want to ask how codeState i want convert: Euro on lira or rupie on kuna etc..
    I know formula:
    meziResult = summ * [(exchangeRate / quantity) /* default code */]
    Result = ( meziResult * [quantity) /* on what we want convert = end Code */] / [exchangeRate /* end code */]

    when i asking on stateCode i'm going get only code but i need his quantity and exchangeRate on operating with it
    Last edited by Siggi; 12-30-2014 at 06:40 AM.

  8. #23
    Registered User
    Join Date
    Sep 2014
    Posts
    364
    Oh, you want work with the values. Actually, you only read the file line by line and don't hold the datas in memory.
    Every time you read a line, the prevous line is gone. So you must hold all lines, or better the extracted datas from the lines.
    There are 2 capabilities:

    1) you input the code and the programm search for the correct line in file and give back the values.
    Then a second time for the second code. If you have the values, you can work with it.

    2) you read in all datas and take it from memory. With this method, you read the file only once.
    If you input the code, you run only through the datas in memory and return the right values.

    But i don't know if you have learned about arrays or structures and memory allocating (malloc, calloc, realloc).
    I have an idea with structures, but if you don't have learned about it, you will be more confused like before.
    Other have classes, we are class

  9. #24
    Registered User
    Join Date
    Dec 2014
    Location
    Czech Republic
    Posts
    36
    We learned only static array not dynamic, so malloc calloc realloc i dont know so well.

    Structures we learned.

  10. #25
    Registered User
    Join Date
    Jun 2014
    Posts
    79
    There are mistakes here and there, but I suppose many of them are translation mistakes.

    Apart from those, you are changing ',' to '.' in the whole line of data. In my opinion it would be safer (and faster) changing just the string representing the numeric data, that is dataPtrs[2] and dataPtrs[4]. Just a minor improvement.

    At some point you ask the user to tell you the source currency code, and he gave you a three characters string. You stored it in "codeState". Ok. You say that you want to make both uppercase and lowercase valid. Well, just convert codeState to all uppercase with something like this:

    Code:
    for( counter=0; counter<3; ++counter )
        codeState[counter] = toupper(codeState[counter]);
    (toupper() is a standard function defined in ctype.h, so include ctype.h)

    Just to be sure, you could convert to uppercase your "code" variable, too.
    Now you can use strcmp() safely, as both "codeState" and "code" contain only uppercase characters.

    If you realize that "codeState" equals to "code", you can save the relevant data taken from the current line and LEAVE THE "for" LOOP WITH A "break" INSTRUCTION (if you don't, you are going to overwrite the data you found with other data that you don't need). Once outside of the "for" loop, you can perform your conversions.

    Ah, don't forget that you have to go back to the beginning of the data file each time you perform a new conversion. Use rewind(mena) for that task, just after "start:" (we are trying to implement the solution that WoodSTokk described at his point #1, so we have to read the file over and over).

    Further revisions could be needed in order to get exactly what you need.
    Last edited by aldo_baldo; 12-30-2014 at 10:59 AM.

  11. #26
    Registered User
    Join Date
    Sep 2014
    Posts
    364
    edit:
    thanks aldo_baldo
    You describe #1 of the list.
    The following is a description of #2

    Okay, not dynamic.
    You can define a structure that hold the information of one country.
    In the main()-function, you define an array with the typ of the structure that is big enough to hold all countries.
    Code:
    # define MAX_CURRENCY 50
    # define MAX_LEN_COUNTRY 30
    # define MAX_LEN_CURRENCY 10
    # define MAX_LEN_CODE 10
    
    typedef struct currency_t {
        char country[MAX_LEN_COUNTRY];
        char currency[MAX_LEN_CURRENCY];
        int quantity;
        char code[MAX_LEN_CODE];
        float course;
    } Currency;
    
    int main(void) {
    
    Currency currency_list[MAX_CURRENCY];
    int currency_now = 0;
    …
    In the loop where you extract the information out of line, you assign the information to the members of the struct-array.
    Don't forget to increment the counter 'currency_now' at end.

    Code:
    …
            strncpy (currency_list[currency_now].country, dataPtrs[0], MAX_LEN_COUNTRY);
            strncpy (currency_list[currency_now].currency, dataPtrs[1], MAX_LEN_CURRENCY);
            currency_list[currency_now].quantity = atol(dataPtrs[2]);
            strncpy (currency_list[currency_now].code, dataPtrs[3], MAX_LEN_CODE);
            currency_list[currency_now].course = atof(dataPtrs[4]);
    
    // make sure to terminate the strings
            currency_list[currency_now].country[MAX_LEN_COUNTRY - 1] = '\0';
            currency_list[currency_now].currency[MAX_LEN_CURRENCY - 1] = '\0';
            currency_list[currency_now].code[MAX_LEN_CODE - 1] = '\0';
    
            if (++currency_now >= MAX_CURRENCY) {
                printf("Too many currencies! exit.\n");
                return -1;
            }
    …
    At the end of the loop, you can close the file.
    All informations are now in the struct-array and the counter hold the number of used entries.
    You can every time loop through the array and search for specific information.
    Last edited by WoodSTokk; 12-30-2014 at 11:32 AM.
    Other have classes, we are class

  12. #27
    Registered User
    Join Date
    Jun 2014
    Posts
    79
    WoodSTokk, you wrote this:

    Code:
    # define MAX_CURRENCY 50
    
    /* ... */
    
    Currency currency_list[MAX_CURRENCY];
    One could decide to make the array as large as needed to include the currency used in the whole world. Consider that there are less than 200 Countries on the planet. Indeed, we could define MAX_CURRENCY as 200 and be safe just with a few KB in memory.

  13. #28
    Registered User
    Join Date
    Sep 2014
    Posts
    364
    Quote Originally Posted by aldo_baldo View Post
    One could decide to make the array as large as needed to include the currency used in the whole world. Consider that there are less than 200 Countries on the planet. Indeed, we could define MAX_CURRENCY as 200 and be safe just with a few KB in memory.
    Yes, i only looked at the file from OP and set MAX_CURRENCY a bit larger and have a security break build in.
    Normaly, i use a dynamic array or linked list, but the OP has not learned about that until now.
    Other have classes, we are class

  14. #29
    Registered User
    Join Date
    Dec 2014
    Location
    Czech Republic
    Posts
    36
    Code:
        printf("\nVychozi mena: ");    
    for(int i = 0; i < 3 ; ++i){
            scanf("%3s", vychoziKod);
            vychoziKod[i] = toupper(vychoziKod[i]);
        }
    It's possible do same thing but print whole array and not printing for letters?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    
    #define ukoncovaciZnak 5
    
    
    typedef struct registrMeny_t {
        char zeme[30];
        char bankovka[10];
        int mnozstvi;
        char kod[10];
        float kurz;
    } RegistrMeny;
    
    
    int main(void)
    {
        printf("Dom. ukol c.4.\n");
    
    
        FILE *mena;
        mena = fopen("mena.txt", "r");
    
    
        if(mena == NULL){
            printf("Error: soubor nebyl nalezen.\nPokud soubor existuje: prejmenujejte jej na mena.txt.\n");
            return 1;
        }
    
    
        char radek[50], *kod, vychoziKod[4], cilovyKod[4], instrukce;
        float suma=0, kurz, meziVysl=0, vysl=0;
        int mnozstvi;
    
    
    
    
    zacatek:
        rewind(mena);
    
    
        printf("\nKolik si prejete prevest: ");
        scanf("%f", &suma);
    
    
        printf("\nVychozi mena: ");
        for(int i = 0; i < 3 ; ++i){
            scanf("%3s", vychoziKod);
            vychoziKod[i] = toupper(vychoziKod[i]);
        }
    
    
        printf("\nCilova mena: ");
        scanf("%3s", cilovyKod);
    
    
        for(int i = 0; fgets(radek, 50, mena) != NULL; ++i){
            if(i > 1){
                char *data = radek;
                char *dataPtrs[ukoncovaciZnak];
    
    
                RegistrMeny seznamMeny[50];
                int aktualniMena = 0;
    
    
                for(dataPtrs[0] = data, i = 1; i < ukoncovaciZnak; ++i){
                    dataPtrs[i] = strchr(dataPtrs[i-1], '|')+1;
                }
                for(int i = 0; data[i] != '\0'; ++i){
                    if(data[i] == '|' || data[i] == '\n')
                       data[i] = '\0';
                    if(data[i] == ',')
                       data[i] = '.';
                }
    
    
                strncpy(seznamMeny[aktualniMena].zeme, dataPtrs[0], 30);
                strncpy(seznamMeny[aktualniMena].bankovka, dataPtrs[1], 10);
                seznamMeny[aktualniMena].mnozstvi = atol(dataPtrs[2]);
                strncpy (seznamMeny[aktualniMena].kod, dataPtrs[3], 10);
                seznamMeny[aktualniMena].kurz = atof(dataPtrs[4]);
    
    
                printf("%4ld %s = %.3f\n", seznamMeny[aktualniMena].mnozstvi , seznamMeny[aktualniMena].kod, seznamMeny[aktualniMena].kurz);
    
    
                if(strcmp(seznamMeny[aktualniMena].kod, vychoziKod) ==  NULL){
                    meziVysl = suma * (seznamMeny[aktualniMena].kurz / (float)seznamMeny[aktualniMena].mnozstvi);
               /*         printf("\n%.3f", suma);
                        printf("\n%.3f", seznamMeny[aktualniMena].kurz);
                        printf("\n%d", seznamMeny[aktualniMena].mnozstvi);   <--- testing
                        printf("\n%.3f\n", meziVysl);
                }*/
    
    /** Question **/
      /* when i had there other if (i will paste)
      if(strcmp(seznamMeny[aktualniMena].kod, cilovyKod) == NULL){
      vysl = (meziVysl /  seznamMeny[aktualniMena].kurz) * (float)seznamMeny[aktualniMena].mnozstvi);
    
    so there theese two if fighting each other ... i must have twice that cyclo? or i can somehow save place?
    
    */
    
                seznamMeny[aktualniMena].zeme[30 - 1] = '\0';
                seznamMeny[aktualniMena].bankovka[10 - 1] = '\0';
                seznamMeny[aktualniMena].kod[10 - 1] = '\0';
    
    
                if(++aktualniMena >= 50){
                    printf("Error: prilis mnoho informaci!\n");
                    return -1;
                }
    
    
                ++aktualniMena;
            }
        }
        puts("\n");
    
    
    operace:
        printf("\nPokracovat v zadavani: a/n\n");
        scanf("%c", &instrukce);
        scanf("%c", &instrukce);
    
    
        switch(instrukce){
            case 'n': case 'N':{
                goto konec;
            }
            case 'a': case 'A':{
                goto zacatek;
            }
            default:{
                printf("Neplatna instrukce.\n\n");
                goto operace;
            }
        }
    konec:
    
    
        fclose(mena);
    
    
        puts("\nKonec programu.");
        return 0;
    }
    I'm a bit confusion, but it'll be okay. I have few questions in code.
    (Don't be angry, again in my langauge, but i hope u will not need theese words.)
    Last edited by Siggi; 12-30-2014 at 02:02 PM.

  15. #30
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    If you want to use a label and goto for cleanup, that could work. However, what I see here is that you're using goto where you should be using loops or separating your code into functions.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Ignoring the stdio.h file in a c file
    By Raj 89 in forum C Programming
    Replies: 4
    Last Post: 11-28-2012, 11:08 AM
  2. removing/ignoring carrage returns from a file
    By katipo in forum C Programming
    Replies: 3
    Last Post: 12-01-2008, 03:55 PM
  3. Ignoring line in C++ when reading from file
    By falzone in forum C++ Programming
    Replies: 7
    Last Post: 11-16-2007, 12:08 AM
  4. File information in C
    By jakewendt in forum C Programming
    Replies: 2
    Last Post: 10-11-2002, 04:12 PM
  5. Ignoring a word from a .txt file
    By TrojanGekko in forum C++ Programming
    Replies: 1
    Last Post: 01-21-2002, 05:14 PM