You're close. Here's a working version of your code. Note that the scanf() leaves the newline from the number for the ... fgets(), because you won't ever use gets() again, will you? ... so you need to read up to and including the newline after the scanf(). Of course, there's the interesting question of 'why do people think it is better for humans to count than to make computers count instead?' It would be more sensible not to bother with the count. Note that the revised code validates n to ensure it is not larger than 50.
Revised code that works on lines of length 9 or shorter
#include <assert.h>
#include <stdio.h>
#include <string.h>
void sort(char s[50][10], int);
int main(void)
{
int i;
int n = 0;
char s[50][10];
char line[11];
if (scanf("%d", &n) != 1)
{
fprintf(stderr, "Failed to read a number\n");
return 1;
}
if (n <= 0 || n > 50)
{
fprintf(stderr, "%d is out of the range 1..50\n", n);
return 1;
}
// Gobble rest of first line
while ((i = getchar()) != EOF && i != '\n')
;
for (i = 0; i < n; i++)
{
if (fgets(line, sizeof(line), stdin) == 0)
break;
// Remove newline from input
size_t len = strlen(line);
assert(len > 0 && len <= sizeof(s[i]));
line[len-1] = '\0';
strcpy(s[i], line);
}
n = i; // In case the file was shorter than stated!
printf("Before:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
sort(s, n);
printf("After:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
return 0;
}
void sort(char s[50][10], int n)
{
int i, j, cmp;
char tmp[10];
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++)
{
for (j = 0; j < n-1; j++)
{
cmp = strcmp(s[j], s[j+1]);
if (cmp > 0)
{
strcpy(tmp, s[j+1]);
strcpy(s[j+1], s[j]);
strcpy(s[j], tmp);
}
}
}
}
This code reads lines into a string long enough to take up to 9 data characters, a newline, and the terminal null. It removes the newline, leaving up to 9 data characters and a terminal null.
Sample run:
Before:
Number 34
Number 39
Number 32
Number 30
Number 22
Number 34
Number 57
Number 28
Number 30
Number 47
Number 43
Number 23
Number 22
After:
Number 22
Number 22
Number 23
Number 28
Number 30
Number 30
Number 32
Number 34
Number 34
Number 39
Number 43
Number 47
Number 57
Original code that works on lines of length 8 or shorter
#include <assert.h>
#include <stdio.h>
#include <string.h>
void sort(char s[50][10], int);
int main(void)
{
int i;
int n = 0;
char s[50][10];
if (scanf("%d", &n) != 1)
{
fprintf(stderr, "Failed to read a number\n");
return 1;
}
if (n <= 0 || n > 50)
{
fprintf(stderr, "%d is out of the range 1..50\n", n);
return 1;
}
// Gobble rest of first line
while ((i = getchar()) != EOF && i != '\n')
;
for (i = 0; i < n; i++)
{
if (fgets(s[i], sizeof(s[i]), stdin) == 0)
break;
// Remove newline from input
size_t len = strlen(s[i]);
assert(len > 0);
s[i][len-1] = '\0';
}
n = i; // In case the file was shorter than stated!
printf("Before:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
sort(s, n);
printf("After:\n");
for (i = 0; i < n; i++)
printf("%s\n", s[i]);
return 0;
}
void sort(char s[50][10], int n)
{
int i, j, cmp;
char tmp[10];
if (n <= 1)
return; // Already sorted
for (i = 0; i < n; i++)
{
for (j = 0; j < n-1; j++)
{
cmp = strcmp(s[j], s[j+1]);
if (cmp > 0)
{
strcpy(tmp, s[j+1]);
strcpy(s[j+1], s[j]);
strcpy(s[j], tmp);
}
}
}
}
The 'big' change is the way the function array parameter is declared and defined. You're passing an array of 50 rows with 10 characters per row, so simply specify that in the function. You could drop the 50 from the dimensions of the function parameter with no change to the program's behaviour.
Sample input:
8
fed
abc
cba
def
hij
cba
xyz
aaa
Example run:
$ ./srt < data
Before:
fed
abc
cba
def
hij
cba
xyz
aaa
After:
aaa
abc
cba
cba
def
fed
hij
xyz
$
The fact that this needed revising shows the importance of testing the limits (and carefully defining the limits).
The code as revised is still not general purpose code. The fixed limit of at most 50 lines of input, the count of the number of lines required as part of the input, and the fixed line length of at most 10 characters per line all make it toy code. As such, GIGO (garbage in, garbage out) is not an unreasonable reaction. If the data file contains overlong lines, you get what you get. The code won't crash, but the output may not make much sense.
sort()takes different types from the definition ofsort. Using a temporary array of size 10 to copy strings of size 50 seems likely to lead to trouble too.n, so you won't overflow the buffer.gets()! Never usegets(). Pretend it aborts your program. It should be implemented as doing that, in fact, because using it will lead to problems. The first internet worm, the Morris worm from 1988, usedgets()to break in!void sort(char*[50],int);is quite different fromvoid sort(char (*)[50], int);[Note that after your change of array dimensions, it should bechar (*)[10].] And in the definition,void sort(char (*s)[10], int n) { /* body */ }. Also note thatfor(i=0;i<=n;i++)should befor(i = 0; i < n; i++).