Thread: Help! - FILE - sort alphabetically

  1. #16
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    The only reason I'm able to help you Juan, is because you have posted some code. That's a rule on the forum, because otherwise we become the "short order" center for students to get their homework and projects, coded for them, without them working on it. You can see the problem in that scenario.

    Spend some time learning in the C tutorial for this forum - (link is at the top center of this website) it is excellent in content, and you will know how to read names from a text file, one name to a line, using fscanf(). The idea is not to keep you "not so good", and have you rely on others for all your code. We were all "not so good", before we studied and practiced.

    Post that up, and then we can continue a bit further. I'll be running around for a few hours, so you'll have time to study.

    I need you to post up code to open a text file with 10 names in it, one name per line of text, and print them. Don't forget to close the file after you have finished reading in the names.

  2. #17
    Registered User
    Join Date
    Feb 2014
    Posts
    105
    Thanks for your answers!

    This is what I could do.. it doesn't work and I don't know why. All the names are written by the user (I don't know how to take them from a .txt)

    Code:
    int main()
    {
        int N;
        printf("\nNumber of names: ");
        scanf("%d", &N);
    
        char name[N][20];
        char aux[N][20];
        int i, ret0=0, ret1=0, ret2=0, ret3=0;
    
        for(i=0; i<N; i++)
        {
            printf("\nName: ");
            scanf("%s", &name[i][20]);
        }
    
        // 3 lower names
        printf("\nFIRST 3 NAMES SORTED ALPHABETICALLY\n");
        for (i=0; i<3; i++)
        {
            ret0 = strcmp(name[i][20], name[i+1][20]);
            if (ret0 > 0)
                name[i][20] = aux[i][20];
                name[i][20] = name[i+1][20];
                name[i+1][20] = aux[i][20];
    
        }
        printf("\n%s ", &name[0][20]);
        printf("\n%s ", &name[1][20]);
        printf("\n%s ", &name[2][20]);
    
    
        printf("\n3 LOWER NAMES\n");
        for(i=3; i<N; i++)
        {
            if ((ret1 = strcmp(name[0][20], name[i][20])) > 0 && (ret2 = strcmp(name[1][20], name[i][20])) > 0 && (ret3 = strcmp(name[2][20], name[i][20])) > 0)
            {
                name[0][20] = name[i][20];
                name[1][20] = name[0][20];
                name[2][20] = name[1][20];
            }
            if ((ret1 = strcmp(name[0][20], name[i][20])) < 0 && (ret2 = strcmp(name[1][20], name[i][20])) > 0 && (ret3 = strcmp(name[2][20], name[i][20])) > 0)
            {
                name[2][20] = name[i][20];
            }
            if ((ret1 = strcmp(name[0][20], name[i][20])) > 0 && (ret2 = strcmp(name[1][20], name[i][20])) < 0 && (ret3 = strcmp(name[2][20], name[i][20])) > 0)
            {
                name[1][20] = name[i][20];
                name[2][20] = name[1][20];
            }
        }
        printf("\n%s \n%s \n%s", name[0][20], name[1][20], name[2][20]);
    
        return 0;
    }
    What I intended to do is to compare all the names with the first 3 names (sorted alphabetically) and to print them


  3. #18
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    That's much better. Not a bad start, but your sort function doesn't scale well, i.e. if you have more than 3 names to sort, you would need lots of if statements. Better to use nested loops. As I mentioned, read up on some sorting algorithms on Wikipedia. I'll start with a few general tips:

    1. Post complete code, including any header files you are using. You wrote the code, and know which functions you used, so should know which header files you need to include. It's a pain for us to find out by trial and error.
    2. Compile at the maximum warning level. Fix all warnings and errors you can. If you can't fix some of them, post them exactly as they are (copy-paste the entire message with line numbers). See below for what I get when I compile your code.
    3. Give more details. When you post a question, please provide the exact input you give the program, the exact (incorrect) output you get, and the correct output you expect to see. It helps us immensely, instead of guessing at which of the infinite possibilities of input you give. Either post the input file or copy-paste your terminal session.


    Now, as for the code you posted, it has a lot of warnings:
    Code:
    $ make foo
    gcc -Wall -ggdb3 -pedantic -std=gnu99 -O0 -o foo foo.c -lm -lpthread -lrt
    foo.c: In function ‘main’:
    foo.c:24:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:24:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:39:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:39:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:39:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:39:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:39:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:39:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:45:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:45:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:45:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:45:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:45:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:45:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:49:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:49:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:49:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:49:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:49:9: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:49:9: warning: passing argument 2 of ‘strcmp’ makes pointer from integer without a cast [enabled by default]
    /usr/include/string.h:143:12: note: expected ‘const char *’ but argument is of type ‘char’
    foo.c:55:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat]
    foo.c:55:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat]
    foo.c:55:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘int’ [-Wformat]
    That looks like a lot, but really it's all due to one misunderstanding, and is easy to fix.

    strcmp requires a string, not a single char. You got this right in post #7. In C, an array with SIZE elements has valid indexes of 0..SIZE-1. So if array[i] has 20 chars, then valid indexes are array[i][0] to array[i][19]. array[i][20] does not represent the whole name, instead it is trying to access a single element (i.e. a char, not a string/name), but is out of bounds -- accessing an invalid element. Also, printf with the %s modifier requires a string, not a single char.

    Remember how, in post #7, you dropped the brackets to refer to the array as a whole? Similar thing here. If array[10][20] is the array of names/strings, then array[0] is a single name/string. Drop the right-most set of brackets when you want to refer to the whole string/name.
    Make sense?

    One more note, you can't assign strings like you're doing (i.e. you can't use = like you would for an int). You need to use strcpy to copy them from one location to another. You will need an extra temporary array when you "swap" them.

    I recommend you do this in steps, like the ones you listed in post #14, maybe even smaller than those. Something like:

    1. Make sure you can read from a file. Start with a program that simply reads each name from a file, and prints it back out. Make sure you check the return value of fopen, fgets/fscanf, etc, and print out an error message if there's a problem.
    2. Then, define a constant for how many names you want from the file (called something like NUM_NAMES, with a value of 100 for the final problem, something smaller like 5 or 10 for testing). Also define a constant for the maximum name length (e.g. MAX_NAME_LEN). Declare an array of size NUM_NAMES x MAX_NAME_LEN, and read the file. Store the first NUM_NAMES into the array, and simply print out the rest. Print out the array when done to make sure you read in the first NUM_NAMES names correctly.
    3. Write a sort function to sort the array of names. Call it, passing in the array of names and the number of elements (NUM_NAMES). Print out the array when done, to ensure it was sorted correctly.
    4. Write a function that either inserts a name if it belongs (bumping the rest of them down), or does nothing if the name is bigger than all the names currently in the array.
    5. Test that function with a few names -- you can hard-code these in your .c file.
    6. Integrate your insert function with the loop that reads all the rest of the names.


    It's important to work in small steps, maybe only 5-10 lines of code at a time. Compile (at max warning level), fix all errors/warnings, then test your code to make sure it works, fixing any bugs you find. Don't move on to the next step until all previous code is working perfectly.

  4. #19
    Registered User
    Join Date
    Feb 2014
    Posts
    105
    Thank you very much, anduril, for your answer!

    I'm just fixing everything! I hope I can post the code in some hours. Now, I'm going to post two codes of different exercises in another thread that are not working correctly. I hope you can also help me with them!

    This is the best forum in the world

  5. #20
    Registered User
    Join Date
    Feb 2014
    Posts
    105
    This is the last program I have to finish today! Can you continue helping me with this one?
    Thanksss

  6. #21
    Registered User
    Join Date
    Feb 2014
    Posts
    105
    This doesn't work. What I'm trying to do is: if name[i] > name[i+1], we put the name that is in name[i+1] in name[i] and the name that is in name[i] in name[i+1]

    Any help?

    Code:
        for (i=0; i<3; i++)
        {
            ret0 = strcmp(name[i][20], name[i+1][20]);
            if (ret0 > 0)
            {
                strcpy(aux[i][20], name[i][20]);
                strcpy(name[i][20], name[i+1][20]);
                strcpy(name[i+1][20], aux[i][20]);
            }
    
        }

    Thanks!
    Last edited by juanjuanjuan; 02-16-2014 at 11:56 AM.

  7. #22
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Your compiler should be warning you about something. What is the warning message and what do you understand of it? Related to this: what is the type of name[i][20]?
    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

  8. #23
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by anduril462 View Post

    Remember how, in post #7, you dropped the brackets to refer to the array as a whole? Similar thing here. If array[10][20] is the array of names/strings, then array[0] is a single name/string. Drop the right-most set of brackets when you want to refer to the whole string/name.
    Make sense?
    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  9. #24
    Registered User
    Join Date
    Feb 2014
    Posts
    105
    if I don't write '20' between the left brackets, it says:
    error: expected expression before ']' token

    If I put '20', it says:
    warning: implicit declaration of function 'strcmp'
    warning: implicit declaration of function 'strcpy'

  10. #25
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The implicit declarations mean you forgot to include <string.h>

    Can you really not see the pattern between array[20] -> array so therefore array[i][20] -> array[i]?

  11. #26
    Registered User
    Join Date
    Feb 2014
    Posts
    105
    Perfect! Now, I has no errors and no warnings, but it doesn't work! When I compile the program, it has an error and stop working

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
        int N;
        printf("\nNumber of names: ");
        scanf("%d", &N);
    
        char name[N][20];
        char aux[N][20];
        int i, ret0=0, ret1=0, ret2=0, ret3=0;
    
        for(i=0; i<N; i++)
        {
            printf("\nName: ");
            scanf("%s", &name[i][20]);
        }
    
        // 3 lower names
        printf("\nFIRST 3 NAMES SORTED ALPHABETICALLY\n");
        for (i=0; i<3; i++)
        {
            ret0 = strcmp(name[i][20], name[i+1][20]);
            if (ret0 > 0)
            {
                strcpy(aux[i][20], name[i][20]);
                strcpy(name[i][20], name[i+1][20]);
                strcpy(name[i+1][20], aux[i][20]);
            }
    
        }
        printf("\n%s ", &name[0][20]);
        printf("\n%s ", &name[1][20]);
        printf("\n%s ", &name[2][20]);
    
    
        printf("\n3 LOWER NAMES\n");
        for(i=3; i<N; i++)
        {
            if ((ret1 = strcmp(name[0][20], name[i][20])) > 0 && (ret2 = strcmp(name[1][20], name[i][20])) > 0 && (ret3 = strcmp(name[2][20], name[i][20])) > 0)
            {
                name[0][20] = name[i][20];
                name[1][20] = name[0][20];
                name[2][20] = name[1][20];
            }
            if ((ret1 = strcmp(name[0][20], name[i][20])) < 0 && (ret2 = strcmp(name[1][20], name[i][20])) > 0 && (ret3 = strcmp(name[2][20], name[i][20])) > 0)
            {
                name[2][20] = name[i][20];
            }
            if ((ret1 = strcmp(name[0][20], name[i][20])) > 0 && (ret2 = strcmp(name[1][20], name[i][20])) < 0 && (ret3 = strcmp(name[2][20], name[i][20])) > 0)
            {
                name[1][20] = name[i][20];
                name[2][20] = name[1][20];
            }
        }
        printf("\n%s \n%s \n%s", name[0][20], name[1][20], name[2][20]);
    
        return 0;
    }
    The part that is not working is this:

    Code:
        printf("\nFIRST 3 NAMES SORTED ALPHABETICALLY\n");
        for (i=0; i<3; i++)
        {
            ret0 = strcmp(name[i][20], name[i+1][20]);
            if (ret0 > 0)
            {
                strcpy(aux[i][20], name[i][20]);
                strcpy(name[i][20], name[i+1][20]);
                strcpy(name[i+1][20], aux[i][20]);
            }
    
        }
        printf("\n%s ", &name[0][20]);
        printf("\n%s ", &name[1][20]);
        printf("\n%s ", &name[2][20]);

    Thanks!

  12. #27
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Please post the code that compiles without warnings!
    I got 29 warnings with the code you posted!

    Most if not all like this "'strcmp' makes pointer from integer without a cast"

    Tim S.
    Last edited by stahta01; 02-16-2014 at 01:49 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  13. #28
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    For the love of all that is good, remove ALL the [20] things EXCEPT the one (one!) in the declaration of the array.

  14. #29
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by tabstop View Post
    For the love of all that is good, remove ALL the [20] things EXCEPT the one (one!) in the declaration of the array.
    There are really two array declarations that need the [20].

    Tim S.
    Last edited by stahta01; 02-16-2014 at 02:00 PM. Reason: Grammar
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  15. #30
    Registered User
    Join Date
    Feb 2014
    Posts
    105
    OK. I removed all the '20' except those which were in the declaration of the array.

    Now, I have 20 errors and 5 warnings.. all the errors are: expected expression before ']' token

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
        int N;
        printf("\nNumber of names: ");
        scanf("%d", &N);
    
        char name[N][20];
        char aux[N][20];
        int i, ret0=0, ret1=0, ret2=0, ret3=0;
    
        for(i=0; i<N; i++)
        {
            printf("\nName: ");
            scanf("%s", &name[i][]);
        }
    
        // 3 lower names
        printf("\nFIRST 3 NAMES SORTED ALPHABETICALLY\n");
        for (i=0; i<3; i++)
        {
            ret0 = strcmp(name[i][], name[i+1][]);
            if (ret0 > 0)
            {
                strcpy(aux[i][], name[i][]);
                strcpy(name[i][], name[i+1][]);
                strcpy(name[i+1][], aux[i][]);
            }
    
        }
        printf("\n%s ", &name[0][]);
        printf("\n%s ", &name[1][]);
        printf("\n%s ", &name[2][]);
    
    
        printf("\n3 LOWER NAMES\n");
        for(i=3; i<N; i++)
        {
            if ((ret1 = strcmp(name[0][], name[i][])) > 0 && (ret2 = strcmp(name[1][], name[i][])) > 0 && (ret3 = strcmp(name[2][], name[i][])) > 0)
            {
                name[0][] = name[i][];
                name[1][] = name[0][];
                name[2][] = name[1][];
            }
            if ((ret1 = strcmp(name[0][], name[i][])) < 0 && (ret2 = strcmp(name[1][], name[i][])) > 0 && (ret3 = strcmp(name[2][], name[i][])) > 0)
            {
                name[2][] = name[i][];
            }
            if ((ret1 = strcmp(name[0][], name[i][])) > 0 && (ret2 = strcmp(name[1][], name[i][])) < 0 && (ret3 = strcmp(name[2][], name[i][])) > 0)
            {
                name[1][] = name[i][];
                name[2][] = name[1][];
            }
        }
        printf("\n%s \n%s \n%s", name[0][], name[1][], name[2][]);
    
        return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 9
    Last Post: 04-01-2011, 04:13 PM
  2. Arranging a file into alphabetical order.
    By Malachi in forum C Programming
    Replies: 18
    Last Post: 02-10-2009, 11:07 PM
  3. Replies: 4
    Last Post: 03-06-2008, 03:38 PM
  4. Binary File - Byte order / endian
    By chico1st in forum C Programming
    Replies: 27
    Last Post: 08-22-2007, 07:13 PM
  5. Header file include order
    By cunnus88 in forum C++ Programming
    Replies: 6
    Last Post: 05-17-2006, 03:22 PM