Write a C function longestStrInAr()
that takes in an array of strings str
and size
(>0) as
parameters, and returns the longest string and also the length of the longest string via the
pointer parameter length. If two or more strings have the same longest string length, then the
first appeared string will be returned to the calling function. For example, if size
is 5
and the
array of strings is { "peter", "john", "mary", "jane", "kenny"}
, then the longest string is "peter"
and
the string length is 5
will be returned to the calling function
I am getting a segmentation fault here and I don't know why.
#include <stdio.h>
#include <string.h>
#define N 20
char *longestStrInAr(char str[N][40], int size, int *length);
int main() {
int i, size, length;
char str[N][40], first[40], last[40], *p, *result;
char dummychar;
printf("Enter array size: \n");
scanf("%d", &size);
scanf("%c", &dummychar);
for (i = 0; i < size; i ) {
printf("Enter string %d: \n", i 1);
fgets(str[i], 40, stdin);
if (p = strchr(str[i], '\n'))
*p = '\0';
}
result = longestStrInAr(str, size, &length);
printf("longest: %s \nlength: %d\n", result, length);
return 0;
}
char *longestStrInAr(char str[N][40], int size, int *length) {
char *p;
for (int i = 0; i < size; i ) {
int j = 0; int max = 0, *length = 0;
while (str[i][j ] != '\0') {
max ;
}
if (max > *length) {
*length = max;
p = str[i];
}
}
return p;
}
CodePudding user response:
The line
int j = 0; int max = 0, *length = 0;
is bad. A new pointer variable length
is declared here and initialized to NULL
, shadowing the argument length
.
After that, this length
(NULL
) is dereferenced and it will cause Segmentation Fault.
To initialize what is pointed at by the argument length
to zero, the line should be:
int j = 0, max = 0; *length = 0;
CodePudding user response:
In function longestStrInAr
, the code in the for
loop is incorrect:
int j = 0; int max = 0, *length = 0;
defines 3 local variables: j
, max
and length
as a new pointer to int
, initialized as a null pointer. This length
variable has the same name as the function argument but is defined in the scope of the block that is the body of the for
statement, hence it shadows the argument with the same name. This problem would have been diagnosed by the compiler if given a higher level of warnings (gcc -Wall -Wextra -Wshadow, clang -Weverything).
This is causing the segmentation fault: when you later dereference this pointer in if (max > *length)
, you have undefined behavior as length
is a null pointer.
You probably meant to just use the argument and initialize *length
, and you should do this before the for
loop. Note also that you should initialize p
as p = str[0]
for the pathological case where all strings are empty for which the posted code returns an uninitialized pointer. As a matter of fact, there is another special case to consider: if size
is 0
, the function should return NULL
.
There are some problems in the main
function too: if size
is greater than N
, you read strings beyond the end of the array.
Here is a modified version:
#include <stdio.h>
#define N 20
char *longestStrInAr(char str[][40], int size, int *length);
int flush_input(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
int main() {
int i, size, length;
char str[N][40];
char *result;
printf("Enter array size: \n");
if (scanf("%d", &size) != 1 || size < 0 || size > N) {
fprintf(stderr, "invalid input\n");
return 1;
}
// read and discard the rest of the input line
flush_input();
for (i = 0; i < size; i ) {
printf("Enter string %d: \n", i 1);
str[i][0] = '\0';
scanf("9[^\n]", str[i]);
flush_input();
}
result = longestStrInAr(str, size, &length);
printf("longest: %s \nlength: %d\n",
result ? result : "(null)", length);
return 0;
}
char *longestStrInAr(char str[][40], int size, int *length) {
char *p = NULL;
*length = 0;
if (size > 0) {
for (int i = 0; i < size; i ) {
int j = 0;
while (str[i][j] != '\0')
j ;
if (*length < j) {
*length = j;
p = str[i];
}
}
}
return p;
}