Thread: Swapping strings around in an array

  1. #1
    Registered User
    Join Date
    Jul 2014
    Posts
    50

    Swapping strings around in an array

    Hi,

    I want to swap all the strings around in my array that have come from a file so they're in ascending order.

    The .txt file is:

    341949 English 7
    487476 English 83
    528191 English 59
    003953 English 88
    075160 English 34
    713494 English 42
    765251 English 40
    400683 English 52
    843007 English 71
    421311 English 47
    421311 Mathematics 52
    580313 English 91
    580313 Mathematics 97
    421311 Physics 74
    223170 English 81
    131782 English 51
    421311 Computing 11
    528191 Mathematics 85
    886030 English 84
    832912 English 94
    003953 Mathematics 29
    073241 English 99
    131782 Mathematics 59
    075160 Mathematics 92
    580313 Physics 63
    073241 Mathematics 32
    487476 Mathematics 73
    075160 Physics 98
    472832 English 44
    713494 Mathematics 0
    400683 Mathematics 72
    765251 Mathematics 27
    599828 English 11
    713494 Physics 48
    223170 Mathematics 49
    580313 Computing 78
    765251 Physics 42
    843007 Mathematics 48
    487476 Physics 85
    832912 Mathematics 62
    832912 Physics 72
    223170 Physics 54
    341949 Mathematics 45
    487476 Computing 76
    886030 Mathematics 20
    868717 English 2
    223170 Computing 72
    868717 Mathematics 37
    659183 English 57
    659183 Mathematics 67
    528191 Physics 8
    341949 Physics 48
    843007 Physics 40
    341949 Computing 41
    472832 Mathematics 88
    472832 Physics 91
    472832 Computing 95
    131782 Physics 97
    073241 Physics 73
    528191 Computing 49
    868717 Physics 49
    886030 Physics 39
    075160 Computing 80
    599828 Mathematics 57
    400683 Physics 57
    400683 Computing 16
    659183 Physics 65
    073241 Computing 63
    713494 Computing 38
    886030 Computing 25
    843007 Computing 98
    868717 Computing 15
    832912 Computing 63
    003953 Physics 83
    131782 Computing 38
    765251 Computing 95
    659183 Computing 22
    003953 Computing 38
    599828 Physics 99
    599828 Computing 86

    My program successfully uses fgets() and then prints the strings back to the screen just to demonstrate the strings have been stored, but now I want to arrange these strings in an order like this:

    341949 Computing 41
    341949 English 7
    341949 Mathematics 45
    341949 Physics 48

    And then print them on the screen to show it works so can write them to a file so all the student IDS are in some kind of ascending order with their subject and mark next to each ID.

    If you look at my code I think the problem is with my swap function. I'm not sure what the parameters would be when I'm swapping strings as opposed towards elements of an array.

    Code:
    #include <stdio.h>
    #include <string.h>
    #define LENGTH 23
    #define LINES 80
    
    
    void swap( char *x, char *y)
    {
          char temp=*x;
          *x=*y;
          *y=temp;
    
     
    
    }
    
    int main(void)
    {
          int i=0,j,k;
    
          FILE *input_file;
    
          char file[LENGTH];
          char string[LINES][LENGTH];
    
          if((input_file=fopen("C:\\file\\file.txt", "r"))==NULL)
               perror("File open failed");
          else
          {
               while(fgets(file, LENGTH, input_file)!=NULL)
               {
                    strcpy(string[i], file);
       
                    i++;
    
                    printf("%s", string[i]);
     
    
              }
          }
     
          for(j=0; j<LINES; j++)
          {
               for(k=0; k<LINES; k++)
               {
    
               if(strcmp(string[k],string[j])>0)
                   swap(string[j], string[k]);
               }
         }
     
     
    
     return 0;
    }
    Last edited by Tripswitch; 08-02-2014 at 05:53 AM.

  2. #2
    Registered User zub's Avatar
    Join Date
    May 2014
    Location
    Russia
    Posts
    104
    Create array of pointers, then sort it.

    qsort - C++ Reference
    Last edited by zub; 08-02-2014 at 06:24 AM.
    Our goals are clear, tasks are defined! Let's work, comrades! -- Nikita Khrushchev

  3. #3
    Registered User
    Join Date
    Jul 2014
    Posts
    50
    Can you look at my code please. I'm trying to use the qsort function, it compiles fine but crashes when it comes to running it. Also, I'm not sure if I've defined my array of pointers correctly.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define STRING_LENGTH 23
    #define NUMBER_OF_LINES 80  
    
    int string_compare(void const *x, void const *y)
    {
     return strcmp(*(char**)x, *(char**)y);
    }
    
    
    int main(void)
    {      
          int i=0,j;       
     
          FILE *input_file;       
          char file[STRING_LENGTH];      
          char string[NUMBER_OF_LINES][STRING_LENGTH]; 
          char (*stringptr[NUMBER_OF_LINES])[STRING_LENGTH];
    
    
          for(i=0;i<NUMBER_OF_LINES;i++)
          {
          stringptr[i]=&string[i];
          }
     
          if((input_file=fopen("C:\\file\\file.txt", "r"))==NULL)           
               perror("File open failed");      
          else      
          {          
               while(fgets(file, STRING_LENGTH, input_file)!=NULL)           
               {                
                    strcpy(string[i], file);
                    printf("%s", string[i]);        
                    i++;                 
            
              }      
          }  
    
          putchar('\n');
    
         qsort(string, sizeof(string)/sizeof(char*), sizeof(char*), string_compare);
    
         for(i=0;i<NUMBER_OF_LINES;i++)
             printf("%s", stringptr[i]);
    
     
        return 0;
    }

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Tripswitch
    it compiles fine but crashes when it comes to running it.
    You need to increase your compiler's warning level:
    Code:
    test.c: In function ‘main’:
    test.c:46:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[23]’ [-Wformat=]
              printf("%s", stringptr[i]);
              ^
    test.c:15:15: warning: unused variable ‘j’ [-Wunused-variable]
           int i=0,j;      
                   ^
    Quote Originally Posted by Tripswitch
    I'm not sure if I've defined my array of pointers correctly.
    You're not. Consider your array of strings:
    Code:
    char string[NUMBER_OF_LINES][STRING_LENGTH];
    You want an array of pointers such that each pointer points to a particular string, or rather the first character thereof. Therefore:
    Code:
    char *stringptr[NUMBER_OF_LINES];
    Then your code to provide initial values to this array must change.

    Also, your qsort call should involve stringptr, not string. (Oh, and perhaps you should be using plural names for these arrays: "string" sounds like a single string and "stringptr" sounds like a single pointer.)
    Last edited by laserlight; 08-04-2014 at 02:52 AM.
    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

  5. #5
    Registered User
    Join Date
    Jul 2014
    Posts
    50
    I'VE DONE IT! IT WORKS!!!

    I don't know what to say, thanks!

  6. #6
    Registered User
    Join Date
    Jul 2014
    Posts
    50
    Hang on, there's a minor problem with the output. I was suspicious about this just using printf() to display the data of the file as it was.

    If you look at the contents of the .txt file, when I print it on the screen using printf() the first line gets a bit of "garbage" appended to the front of it.

    Something like this '\\\ 341949 English 7, where the backslashes look a tiny bit similar to back-to-front upper-case Gamma symbols. When it comes to the qsort(), it arranges the file great, but appends this string with the "garbage" attached at the front of the string to the very end. So it arranges the student IDs in sets of 4 for each subject, gets to the ID 341949, prints 3 of them and then appends the string with garbage to the very end of the file?

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What is your current code?

    EDIT:
    In your code from post #1, you make the curious decision of incrementing i in between reading and printing:
    Code:
                    strcpy(string[i], file);
        
                    i++;
     
                    printf("%s", string[i]);
    This should not affect what was actually stored in the array, yet it is still a mistake since the second string[i] was not yet given an initial value.
    Last edited by laserlight; 08-04-2014 at 04:58 AM.
    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. #8
    Registered User
    Join Date
    Jul 2014
    Posts
    50
    Oh that was a mistake when I was shifting it all around after copy and paste.

    Here's my final working code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define STRING_LENGTH 23
    #define NUMBER_OF_LINES 80  
    
    int string_compare(void const *x, void const *y)
    {
          return strcmp(*(char**)x, *(char**)y);
    }
    
    
    int main(void)
    {      
          int i=0;       
     
          FILE *input_file;       
          char file[STRING_LENGTH];      
          char strings[NUMBER_OF_LINES][STRING_LENGTH]; 
          char *string_ptrs[NUMBER_OF_LINES];
    
    
     
     
          if((input_file=fopen("C:\\file\\file.txt", "r"))==NULL)           
               perror("File open failed");      
          else      
          {          
               while(fgets(file, STRING_LENGTH, input_file)!=NULL)           
               {                
                    strcpy(strings[i], file);
                    printf("%s", strings[i]);        
                    i++;                 
            
              }      
          }  
    
          for(i=0;i<NUMBER_OF_LINES;i++)
          {
          string_ptrs[i]=strings[i];
          }
    
          putchar('\n');
    
          qsort(string_ptrs, sizeof(string_ptrs)/sizeof(char*), sizeof(char*), string_compare);
    
          for(i=0;i<NUMBER_OF_LINES;i++)
               printf("%s", string_ptrs[i]);
    
     
          return 0;
    }
    It's just the first string that gets "garbage" attached to the front of it that's messed it up.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Ah. I see. First problem is this:
    Code:
    while(fgets(file, STRING_LENGTH, input_file)!=NULL)
    The code is correct... if you can guarantee that there will not be more lines in the file that can be stored. I suggest:
    Code:
    int total = 0;
    
    /* ... */
    
    while (total < NUMBER_OF_LINES && fgets(file, STRING_LENGTH, input_file) != NULL)
    {
        file[strcspn(file, "\n")] = '\0'; /* remove trailing newline, if it exists */
        strcpy(strings[total], file);
        printf("%s\n", strings[total]);
        total++;
    }
    After this, instead of using NUMBER_OF_LINES, use total. Since the trailing newlines have been removed, print with "%s\n" instead of "%s".

    The next problem I see is this:
    Code:
    qsort(string_ptrs, sizeof(string_ptrs)/sizeof(char*), sizeof(char*), string_compare);
    The second argument should be the number of elements, which in my revised example means total. If you use sizeof(string_ptrs)/sizeof(char*), then you should get a result equal to NUMBER_OF_LINES, which would not be correct if fewer lines were read than NUMBER_OF_LINES.
    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

  10. #10
    Registered User
    Join Date
    Jul 2014
    Posts
    50
    Nah it's still doing it. Could you copy and paste my data into a text file and see if it does it at your end?

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I compiled and ran this (with a different value for filename) with the test input from your post #1 with no problems:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define STRING_LENGTH 23
    #define NUMBER_OF_LINES 80
    
    int string_compare(void const *x, void const *y)
    {
        return strcmp(*(char**)x, *(char**)y);
    }
    
    int main(void)
    {
        const char *filename = "C:\\file\\file.txt";
    
        int i = 0;
        int total = 0;
    
        FILE *input_file;
        char file[STRING_LENGTH];
        char strings[NUMBER_OF_LINES][STRING_LENGTH];
        char *string_ptrs[NUMBER_OF_LINES];
    
        if ((input_file = fopen(filename, "r")) != NULL)
        {
            while (total < NUMBER_OF_LINES && fgets(file, STRING_LENGTH, input_file) != NULL)
            {
                file[strcspn(file, "\n")] = '\0';
                strcpy(strings[total], file);
                printf("%s\n", strings[total]);
                total++;
            }
        }
        else
        {
            perror("File open failed");
            return EXIT_FAILURE;
        }
    
        for (i = 0; i < total; i++)
        {
            string_ptrs[i] = strings[i];
        }
    
        putchar('\n');
    
        qsort(string_ptrs, total, sizeof(string_ptrs[0]), string_compare);
    
        for (i = 0; i < total; i++)
        {
            printf("%s\n", string_ptrs[i]);
        }
    
        return 0;
    }
    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

  12. #12
    Registered User
    Join Date
    Jul 2014
    Posts
    50
    It must be something to do with my computer, it's still doing it. If I start the .txt file with a new line all IDs are now in order but the "garbage" is just sat at the end of file as a string of its own.

    How do I store my output as a .txt file so I can put it up on here so you can see what I mean?

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Maybe your file was saved with a Unicode byte order mark when it should not have been.
    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

  14. #14
    Registered User
    Join Date
    Jul 2014
    Posts
    50
    See, this is what I'm talking about. This is when I start the .txt file with a new line, do you see what I mean. Is this what you're talking about? Look at the start and end.

    ´╗┐
    341949 English 7
    487476 English 83
    528191 English 59
    003953 English 88
    075160 English 34
    713494 English 42
    765251 English 40
    400683 English 52
    843007 English 71
    421311 English 47
    421311 Mathematics 52
    580313 English 91
    580313 Mathematics 97
    421311 Physics 74
    223170 English 81
    131782 English 51
    421311 Computing 11
    528191 Mathematics 85
    886030 English 84
    832912 English 94
    003953 Mathematics 29
    073241 English 99
    131782 Mathematics 59
    075160 Mathematics 92
    580313 Physics 63
    073241 Mathematics 32
    487476 Mathematics 73
    075160 Physics 98
    472832 English 44
    713494 Mathematics 0
    400683 Mathematics 72
    765251 Mathematics 27
    599828 English 11
    713494 Physics 48
    223170 Mathematics 49
    580313 Computing 78
    765251 Physics 42
    843007 Mathematics 48
    487476 Physics 85
    832912 Mathematics 62
    832912 Physics 72
    223170 Physics 54
    341949 Mathematics 45
    487476 Computing 76
    886030 Mathematics 20
    868717 English 2
    223170 Computing 72
    868717 Mathematics 37
    659183 English 57
    659183 Mathematics 67
    528191 Physics 8
    341949 Physics 48
    843007 Physics 40
    341949 Computing 41
    472832 Mathematics 88
    472832 Physics 91
    472832 Computing 95
    131782 Physics 97
    073241 Physics 73
    528191 Computing 49
    868717 Physics 49
    886030 Physics 39
    075160 Computing 80
    599828 Mathematics 57
    400683 Physics 57
    400683 Computing 16
    659183 Physics 65
    073241 Computing 63
    713494 Computing 38
    886030 Computing 25
    843007 Computing 98
    868717 Computing 15
    832912 Computing 63
    003953 Physics 83
    131782 Computing 38
    765251 Computing 95
    659183 Computing 22
    003953 Computing 38
    599828 Physics 99


    003953 Computing 38
    003953 English 88
    003953 Mathematics 29
    003953 Physics 83
    073241 Computing 63
    073241 English 99
    073241 Mathematics 32
    073241 Physics 73
    075160 Computing 80
    075160 English 34
    075160 Mathematics 92
    075160 Physics 98
    131782 Computing 38
    131782 English 51
    131782 Mathematics 59
    131782 Physics 97
    223170 Computing 72
    223170 English 81
    223170 Mathematics 49
    223170 Physics 54
    341949 Computing 41
    341949 English 7
    341949 Mathematics 45
    341949 Physics 48
    400683 Computing 16
    400683 English 52
    400683 Mathematics 72
    400683 Physics 57
    421311 Computing 11
    421311 English 47
    421311 Mathematics 52
    421311 Physics 74
    472832 Computing 95
    472832 English 44
    472832 Mathematics 88
    472832 Physics 91
    487476 Computing 76
    487476 English 83
    487476 Mathematics 73
    487476 Physics 85
    528191 Computing 49
    528191 English 59
    528191 Mathematics 85
    528191 Physics 8
    580313 Computing 78
    580313 English 91
    580313 Mathematics 97
    580313 Physics 63
    599828 English 11
    599828 Mathematics 57
    599828 Physics 99
    659183 Computing 22
    659183 English 57
    659183 Mathematics 67
    659183 Physics 65
    713494 Computing 38
    713494 English 42
    713494 Mathematics 0
    713494 Physics 48
    765251 Computing 95
    765251 English 40
    765251 Mathematics 27
    765251 Physics 42
    832912 Computing 63
    832912 English 94
    832912 Mathematics 62
    832912 Physics 72
    843007 Computing 98
    843007 English 71
    843007 Mathematics 48
    843007 Physics 40
    868717 Computing 15
    868717 English 2
    868717 Mathematics 37
    868717 Physics 49
    886030 Computing 25
    886030 English 84
    886030 Mathematics 20
    886030 Physics 39
    ´╗┐

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Try saving your file without a byte order mark and see if it makes any difference.
    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. need help in swapping puzzle contain of the array...
    By tianwu in forum C Programming
    Replies: 4
    Last Post: 11-28-2011, 09:08 AM
  2. swapping strings (which are stored in an array)
    By nair in forum C Programming
    Replies: 2
    Last Post: 10-04-2010, 01:27 PM
  3. Swapping rows in a 2D array
    By bassist11 in forum C Programming
    Replies: 5
    Last Post: 03-11-2010, 12:04 PM
  4. Swapping strings in an array of strings
    By dannyzimbabwe in forum C Programming
    Replies: 3
    Last Post: 03-03-2009, 12:28 PM
  5. swapping elements in a 2D array
    By axon in forum C++ Programming
    Replies: 9
    Last Post: 03-10-2003, 02:18 PM