0

I know there are some post about bubblesorting a 2d array in C, but my problem is a little strange as it only occurs with ascending sorting while descending sorting works just fine (and both those algorithms are completely analogical).The only thing I noticed was that ascending sorting printed only a half of each "word".

My program is supposed to bubblesort strings of characters separated with white signs that can be read from standard input or from a file.Reading from standard input is finished with entering a single dot and reading from file ends at EOF.

The code looks like this:

int main()
{ FILE *plik=NULL;
int i,j; 
int k,l; 
int m; 
int a,b; 
char tym; 
char odp; 
char ans;  
char c; 
char tab[100][100];     
char nazwa[100];

printf("Would you like to sort from a file?(Y/N)\n");
scanf("%s",&odp);
if(odp=='n' || odp=='N')
    {printf("Enter character strings and finish with a DOT:\n");
     getc(stdin);   
     i=0;
     j=0;
     while(1)
            {c=getc(stdin);//reading from stdin
            if(c!='\n' && c!='\t' &&c!=' ')
                {tab[i][j]=c;
                if(tab[0][j]=='.')  //ending input
                    {tab[0][j]='\0'; //clearing the extra sign
                     break;}
                 i++;   //columns counter
                 printf("%c",c);}
            else
                 {i=0;
                 j++; //row counter
                 printf("\n");}}}
else if(odp=='y' || odp=='Y')
    {printf ("Enter the file's name:\n");
     scanf("%99s",&nazwa); 
     plik = fopen(nazwa,"rt");
     if(plik==NULL)
        {printf("\nFailed reading from file : %s \n\n",nazwa);    //jesli blad odczytu przerwij dzialanie
         printf("Check the file and try again \n");
         fclose(plik);
         return 0;}
     else
        {i=0;
         j=0;
         do
            {c=getc(plik);
            if(c!='\n' && c!='\t' &&c!=' ')
                {tab[i][j]=c;
                 i++;   //columns counter
                 printf("%c",c);}
            else
                 {i=0;
                 j++; //rows counter
                 printf("\n");}}
         while(c!=EOF);} //ending reading
    } fclose(plik);

  //Here starts the sorting
    printf("\nSelect sorting order (A/D)\n");
    scanf("%s",&ans);
if(ans=='a' || ans=='A') //ascending
    {for(m=0;m<j;m++) //moving to next rows
        for(k=0;tab[k][m]!='\0';k++)//later as in a typical bubblesort
            for(l=0;l<100-1-k;l++)
                if(tab[l][m] > tab[l+1][m])
                    {tym = tab[l+1][m];
                    tab[l+1][m] = tab[l][m];
                    tab[l][m] = tym;}}

else if (ans=='D' || ans=='d') //descending
    {for(m=0;m<j;m++) //moving to next rows
        for(k=0;tab[k][m]!='\0';k++) //later as in typical bubblesort, analogically to ascending order
            for(l=0;l<100-1-k;l++)
                if(tab[l][m] < tab[l+1][m])
                    {tym = tab[l+1][m];
                    tab[l+1][m] = tab[l][m];
                    tab[l][m] = tym;};}

//returning results
a=0;
b=0;
while(b<j)
    {if (tab[a][b]!='\0')
        {putchar(tab[a][b]);
         a++;}
    else
        {a=0;
         b++;
         printf("\n");}

}
return 0;
 }

I am sorry for my English and mess in the code, but I started programming just a month ago. I would be very greatful if someone could help me with this problem. Thank You for Your time :)

MacYou
  • 1
  • 2
    You have four pieces of code to debug: 1) reading from stdin, 2) reading from a file, 3) sort ascending, 4) sort descending. You should create 4 programs. Each program should be used to test one piece. To test 1 and 2, read the strings and then print the strings. To test 3 and 4, start with a known array, e.g. `char tab[100][100] = { "cat", "bear", "dog", "horse" };`, and then sort it and print it. – user3386109 Dec 04 '15 at 20:42
  • 1
    http://stackoverflow.com/help/mcve – Saeid Dec 04 '15 at 21:20
  • for readability, ease of use a documentation tool like `doxygen`, and similar considerations, only one statement per line and (at max) only one variable declaration per statement. Note: consider opening brace '{' and closing brace '}` to each be a statement – user3629249 Dec 04 '15 at 22:27
  • while using 'short' variable names may save some typing, that saved typing will be swamped in the extra effort needed to understand, debug, maintain the program. Suggest using meaningful variable names. The only single char variable names that are easily understood are `j`,`j`, and only when used as array indexs – user3629249 Dec 04 '15 at 22:31
  • when calling `scanf()`, always check the returned value (not the parameter value) to assure the operation was successful – user3629249 Dec 04 '15 at 22:32
  • for readability, Please consistently indent the code. Never use tabs for indenting as each word processor/editor has the tab stops/tab width set differently. indent after every opening brace '{' and un-indent before every closing brace '}'. Suggest using 4 spaces for indenting as that allows several levels of indent across the page and is visible even when using a variable width font. Separate code blocks (for, while, do...while, if, else, switch, case, default) with a blank line – user3629249 Dec 04 '15 at 22:35
  • When compiling, always enable all the warnings, then fix those warnings. (for gcc, at a minimum use: `-Wall -Wextra -pedantic` ) This line: `scanf("%99s",&nazwa);` has a few problems. 1) always check the returned value to assure the operation was successful. suggest:`if( 1 != scanf("%99s",&nazwa) ) { // then scanf failed // handle error and (probably) call exit()}` 2) the parameter `nazwa` is not a `char *`, rather it is `char (*)[100]`. This needs to be corrected. – user3629249 Dec 04 '15 at 22:41
  • regarding this line: `if(tab[0][j]=='.')` By this point in the code, the termination character `.` is already in the table, but it is not part of the desired input. suggest testing the variable `c` before placing it into the table. AND the `.` way placed at `tab[i][j]`, not at `tab[0][j]` unless still on the first row of the table. – user3629249 Dec 04 '15 at 22:50
  • suggest, when a system function returns an error indication, like fopen() returning NULL, call the function: `perror()` as 1) the output will be to `stderr` rather than `stdout` and 2) the appropriate system error message will be output, to tell you what the system thinks caused the problem. Should not be calling `fclose()` for a file that failed to open. – user3629249 Dec 04 '15 at 22:54
  • the statement: `return 0;` indicates to the caller of the program (the OS) that the program was successful. suggest using: `exit( EXIT_FAILURE );` – user3629249 Dec 04 '15 at 22:56
  • the code is exhibiting an mis-understanding. on a `tab[][]` variable declaration, the correct way to look at the variable is: `tab[ row ][ column ] However the code has those items reversed – user3629249 Dec 04 '15 at 22:59
  • the `do...while();` code block that is reading the file is not correct in that it processes `EOF` as if it were a valid input before testing to note that it is not a valid input. – user3629249 Dec 04 '15 at 23:01
  • this line: `scanf("%s",&ans);` is trying to read a string, when `ans` is only a single character. The '%s' format specifier always appends a NUL byte to the input, so will overrun the 'ans' variable, resulting in undefined behaviour and can lead to a seg fault event. suggest: `scanf("%c",&ans);` or better yet: `ans = getchar();` – user3629249 Dec 04 '15 at 23:04
  • the posted code is not appending a NUL byte ('\0') to the end of each string in the tab[][] data, nor is the tab[][] variable being initialized to all '\0', so this kind of line: `for(k=0;tab[k][m]!='\0';k++)` will 'always' fail to properly terminate the loop. There are plenty more problems with the code. Suggest fixing all the commented problems, then appending an edit to the question with the corrected code – user3629249 Dec 04 '15 at 23:12

1 Answers1

0

Apart from

the posted code is not appending a NUL byte ('\0') to the end of each string in the tab[][] data, nor is the tab[][] variable being initialized to all '\0',

the error is in

        for(k=0;tab[k][m]!='\0';k++)//later as in a typical bubblesort
            for(l=0;l<100-1-k;l++)

- the inner loop does not account for the end of string, causing characters to bubble up beyond the string termination and no longer be seen when the sorted string is finally output. This can be rectified by changing the inner loop head to

            for (l=k; l--; )

thus operating only within the string bounds.

Armali
  • 18,255
  • 14
  • 57
  • 171