#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Posts
    9
    Rep Power
    0

    Noob problem in a small code... HELP!


    Hey guys, I just don't know wtf is wrong in my ****ing code. Can you help me please *-*. I would be thankful.

    I need to read my structure but if the user writes END it must end(duhh) xD.

    Ofc it's has more content but atm I am testing the ending feature, and it's not working.

    I've tried 2 ways, but both not working, it just doesn't close when I write END.

    #include <stdio.h>

    int main(){
    int i;


    typedef struct funcionario {
    char nome[100];
    float s1;
    float s2;
    } funcionario;

    funcionario func[100];

    while(func[i].nome != "END"){

    for(i=0; i<100; i++){
    fgets(func[i].nome,100,stdin);
    scanf("%f", &func[i].s1);
    scanf("%f", &func[i].s2);

    }
    }



    return 0;
    }



    -----------------------------------------------------------------------------------------------------------------------

    2nd try:




    #include <stdio.h>

    int main(){
    int i;


    typedef struct funcionario {
    char nome[100];
    float s1;
    float s2;
    } funcionario;

    funcionario func[100];

    while(1){

    for(i=0; i<100; i++){
    fgets(func[i].nome,100,stdin);
    if((func[i].nome[0]=='E') && (func[i].nome[1]=='N') && (func[i].nome[2]=='D'))
    scanf("%f", &func[i].s1);
    scanf("%f", &func[i].s2);

    }
    }



    return 0;
    }




    I'm still a begginer, can I get some help?
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Your first problem is that you are not using code tags

    Here is your first program properly indented:
    Code:
    #include <stdio.h>
    
    int main()
    {
        int i;
    
        typedef struct funcionario 
        {
            char nome[100];
            float s1;
            float s2;
        } funcionario;
    
        funcionario func[100];
    
        while(func[i].nome != "END")
        {
            for(i=0; i<100; i++)
            {
                fgets(func[i].nome,100,stdin);
                scanf("%f", &func[i].s1);
                scanf("%f", &func[i].s2); 
            }
        }
    
        return 0;	
    }
    And your second:
    Code:
    #include <stdio.h>
    
    int main()
    {
        int i;
    
    
        typedef struct funcionario 
        {
            char nome[100];
            float s1;
            float s2;
        } funcionario;
    
        funcionario func[100];
    
        while(1)
        {
            for(i=0; i<100; i++) 
            {
                fgets(func[i].nome,100,stdin);
                if((func[i].nome[0]=='E') && (func[i].nome[1]=='N') && (func[i].nome[2]=='D'))
                    scanf("%f", &func[i].s1);
                scanf("%f", &func[i].s2); 
            }
        }
    
        return 0;	
    }
    You will immediately see that the scanf's that you call when you read in "END" are different in both cases. I will not bother to try to analyze and guess what you are trying to do there. A missing pair of braces may be what's not allowing your second program to do what you expect it to do.

    Next I was going to chastise you for ignoring warnings, but when I compiled your programs I got no warnings. Still, always be sure to turn your warnings on and set to the highest level possible (meaning that the compiler should complain about the most minor problem possible). And never ignore warnings. Warnings are much more important than error messages are. And if your program is throwing warnings at you, then don't even try to run that program, because it is seriously broken.

    Also, since English is not your first language (only determined by your Italian variable names), if you have any problems with my colloquial English, do not hesitate to let me know. I know more than one language so I know how it can be.

    Your second program seems to take care of the problems of your first, except that you are now mishandling the scanf's. But it is still not the right way.

    Here's the problem I see with your first program:
    while(func[i].nome != "END"){
    That does not do what you think it does. func[i].nome is an array name. An array name is a pointer. That means that func[i].nome evaluates to a pointer value, which is a memory address. "END" is a string literal. It has been created somewhere in static memory. When you access "END", it evaluates to the memory address where that string literal is stored. Think about that. When you call strcpy() to copy a string, then that function expects two char pointers, the first to the destination string where the string will be copied to and the second to the source string where the string will be copied from. When you set the source string to a string literal, it evaluates to the memory address of that string, which is what strcpy() needs to do its work.

    So then, what are you actually saying when you say, "while (func[i].nome != "END")" ? You are actually saying that you want to compare the memory addresses of func[i].nome and "END" and that you want to loop while the two memory addresses are not the same. Well, they are not the same. They will never ever be the same. So that condition will forever be true and you will be trapped in that while-loop forever and ever.

    C strings may not seem to make any sense at first, but they really do. There is no basic string type in C, so they came up with a kludge. A "kludge" is solution to a problem which is not elegant. The kludge was that C strings would be char arrays and that the end of the string would be marked with a null-terminator, which is a char whose ASCII code is zero, which is '\0'. In contrast, BASIC and some other software packages (including Turbo Pascal and database programs), would place the length of the string in the first byte of the character array, which arbitrarily limited it to 255 characters; C-style strings could be any length at all.

    As soon as that kludgy convention was adopted, the string.h library functions were created. These are the functions that you use to work with C-style strings. If you want to copy one string's contents to another, then you use strcpy. If you want to compare one string's contents to another, then you use strcmp, "string compare".

    So instead of !=, you wanted to use strcmp() and test for them not being equal. Your second program tests for the first three characters being correct, but if "ENDHAHAHA!!!!!" had been entered, then you would have falsely thought it to be correct. That would not work if you had used strcmp().

    Read the documentation for strcmp(). It returns zero for a match, less than zero for the one string being "less than" the other, and greater than zero for the one string being "greater than" the other. Basically, most of your strcmp() calls will test for a match or no match.
    Last edited by dwise1_aol; May 26th, 2013 at 04:01 AM.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Posts
    9
    Rep Power
    0
    Originally Posted by dwise1_aol
    Your first problem is that you are not using code tags

    Here is your first program properly indented:
    Code:
    #include <stdio.h>
    
    int main()
    {
        int i;
    
        typedef struct funcionario 
        {
            char nome[100];
            float s1;
            float s2;
        } funcionario;
    
        funcionario func[100];
    
        while(func[i].nome != "END")
        {
            for(i=0; i<100; i++)
            {
                fgets(func[i].nome,100,stdin);
                scanf("%f", &func[i].s1);
                scanf("%f", &func[i].s2); 
            }
        }
    
        return 0;	
    }
    And your second:
    Code:
    #include <stdio.h>
    
    int main()
    {
        int i;
    
    
        typedef struct funcionario 
        {
            char nome[100];
            float s1;
            float s2;
        } funcionario;
    
        funcionario func[100];
    
        while(1)
        {
            for(i=0; i<100; i++) 
            {
                fgets(func[i].nome,100,stdin);
                if((func[i].nome[0]=='E') && (func[i].nome[1]=='N') && (func[i].nome[2]=='D'))
                    scanf("%f", &func[i].s1);
                scanf("%f", &func[i].s2); 
            }
        }
    
        return 0;	
    }
    You will immediately see that the scanf's that you call when you read in "END" are different in both cases. I will not bother to try to analyze and guess what you are trying to do there. A missing pair of braces may be what's not allowing your second program to do what you expect it to do.

    Next I was going to chastise you for ignoring warnings, but when I compiled your programs I got no warnings. Still, always be sure to turn your warnings on and set to the highest level possible (meaning that the compiler should complain about the most minor problem possible). And never ignore warnings. Warnings are much more important than error messages are. And if your program is throwing warnings at you, then don't even try to run that program, because it is seriously broken.

    Also, since English is not your first language (only determined by your Italian variable names), if you have any problems with my colloquial English, do not hesitate to let me know. I know more than one language so I know how it can be.

    Your second program seems to take care of the problems of your first, except that you are now mishandling the scanf's. But it is still not the right way.

    Here's the problem I see with your first program:
    while(func[i].nome != "END"){
    That does not do what you think it does. func[i].nome is an array name. An array name is a pointer. That means that func[i].nome evaluates to a pointer value, which is a memory address. "END" is a string literal. It has been created somewhere in static memory. When you access "END", it evaluates to the memory address where that string literal is stored. Think about that. When you call strcpy() to copy a string, then that function expects two char pointers, the first to the destination string where the string will be copied to and the second to the source string where the string will be copied from. When you set the source string to a string literal, it evaluates to the memory address of that string, which is what strcpy() needs to do its work.

    So then, what are you actually saying when you say, "while (func[i].nome != "END")" ? You are actually saying that you want to compare the memory addresses of func[i].nome and "END" and that you want to loop while the two memory addresses are not the same. Well, they are not the same. They will never ever be the same. So that condition will forever be true and you will be trapped in that while-loop forever and ever.

    C strings may not seem to make any sense at first, but they really do. There is no basic string type in C, so they came up with a kludge. A "kludge" is solution to a problem which is not elegant. The kludge was that C strings would be char arrays and that the end of the string would be marked with a null-terminator, which is a char whose ASCII code is zero, which is '\0'. In contrast, BASIC and some other software packages (including Turbo Pascal and database programs), would place the length of the string in the first byte of the character array, which arbitrarily limited it to 255 characters; C-style strings could be any length at all.

    As soon as that kludgy convention was adopted, the string.h library functions were created. These are the functions that you use to work with C-style strings. If you want to copy one string's contents to another, then you use strcpy. If you want to compare one string's contents to another, then you use strcmp, "string compare".

    So instead of !=, you wanted to use strcmp() and test for them not being equal. Your second program tests for the first three characters being correct, but if "ENDHAHAHA!!!!!" had been entered, then you would have falsely thought it to be correct. That would not work if you had used strcmp().

    Read the documentation for strcmp(). It returns zero for a match, less than zero for the one string being "less than" the other, and greater than zero for the one string being "greater than" the other. Basically, most of your strcmp() calls will test for a match or no match.
    I'm from Brazil =P

    it's kind of a test I have to do in my unversity...

    TY anyway but I've changed already the way of doing it xD
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    OK. At least that means that our time zones are not too far apart from each other. The time lags with people in India or Pakistan can be quite a problem.

    Do you understand the inherent problem of using !=?

    Do you understand using strcmp?

    If you can describe how you've "changed already the way of doing it", then that would give us the opportunity of evaluating your "solution."
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Posts
    9
    Rep Power
    0
    hmm... I knew already how to use strcmp, but I will read the text you wrote later, because I don't have much time to finish my stuff hehehehe....

    Here is the way I'm doing now:

    #include <stdio.h>

    int main(){
    int i=0;


    typedef struct funcionario {
    char nome[100];
    float s1;
    float s2;
    } funcionario;

    funcionario func[100];

    while(1){
    fgets(func[i].nome,1000,stdin);
    if((func[i].nome[0]=='F') && (func[i].nome[1]=='I') && (func[i].nome[2]=='M')){
    break;
    }
    scanf("%f", &func[i].s1);
    scanf("%f", &func[i].s2);
    i++;
    }


    return 0;
    }
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Code:
        while(1)
        {
            fgets(func[i].nome,1000,stdin);
            if((func[i].nome[0]=='F') && (func[i].nome[1]=='I') && (func[i].nome[2]=='M'))
            {
                break;
            }
            scanf("%f", &func[i].s1);
            scanf("%f", &func[i].s2);
            i++;
        }
    Now try this:
    Code:
        while(1)
        {
            fgets(func[i].nome,1000,stdin);
            if (strcmp(func[i].nome,"FIM") == 0)
            {
                break;
            }
            scanf("%f", &func[i].s1);
            scanf("%f", &func[i].s2);
            i++;
        }
    Conceptually, does it do the same thing or not? Is it not much more elegant? Elegance is a quality in C programs that is sought out.

    Not having testing it, the only problem I can see is that fgets inserts the newline character(s) into the string, which could cause the strcmp to fail. Which would require the input function to chomp the input string (in Perl, the chomp function does remove the newline character(s)).

    Now suppose that the input string was "FIMMMMMMM!!!!!". Your code would accept that unacceptable input, whereas strcmp would not (assuming the appropriate chomping.
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Hmm. End of the semester? Priorities? Yes, we all know those limitations well.

    There is an entire new life beyond graduation. Your understanding of software should extend far beyond your graduation requirements.

    We will still be here.

IMN logo majestic logo threadwatch logo seochat tools logo