I was trying to print a linked list of first 10 elements of linked list. But I face error while printing or while inputting [duplicate]

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void delspace(char *str);

int main() {
    int i, loops;
    char s1[101], s2[101];

    scanf("%d", &loops);

    while (loops--) {
        fgets(s1, 101, stdin);
        fgets(s2, 101, stdin);
        s1[strlen(s1)] = '\0';
        s2[strlen(s2)] = '\0';

        if (s1[0] == '\n' && s2[0] == '\n') {
            printf("YES\n");
            continue;
        }

        delspace(s1);
        delspace(s2);

        for (i = 0; s1[i] != '\0'; i++)
            s1[i] = tolower(s1[i]);

        for (i = 0; s2[i] != '\0'; i++)
            s2[i] = tolower(s2[i]);

        if (strcmp(s1, s2) == 0) {
            printf("YES\n");
        }
        else {
            printf("NO\n");
        }
    }

    return 0;
}

void delspace(char* str) {
    int i = 0;
    int j = 0;
    char sTmp[strlen(str)];

    while (str[i++] != '\0') {
        if (str[i] != ' ') {
            sTmp[j++] = str[i];
        }
    }
    sTmp[j] = '\0';
    strcpy(str, sTmp);
}

After I entered "loops", "s1" was assigned a blank line automatically. How does it happen? I'm sure my keyboard works fine.


scanf() reads exactly what you asked it to, leaving the following \n from the end of that line in the buffer where fgets() will read it. Either do something to consume the newline, or (my preferred solution) fgets() and then sscanf() from that string.


scanf leaves whitespace in the input buffer, including new-line characters. To use fgets to read the next line you need to manually remove the rest of the current line:

int c;
do{
    c = getchar();
}while(c != EOF && c != '\n');

This is a more Simpler solution

scanf("%d",&loops);
while ((getchar()) != '\n'); //This will consume the '\n' char
//now you're free to use fgets
fgets(string,sizeof(string),stdin);

Geekosaur has answered your question well, I'm just pointing out another "problem" with your code.

The line s1[strlen(s1)] = '\0'; is a no-op if s1 is already properly null terminated BEFORE it executes.

But if s1 is NOT already properly null-terminated BEFORE this line executes (and you're unlucky) it will cause:

  • a SIGSEGV on a POSIX (*nix) system.
  • a GPF on Windows.

This is because strlen basicaly finds the index of the existing null-terminator and returns it! Here's a valid, unoptimized implementation of strlen:

int strlen(char *string) {
    int i = 0;
    while(string[i] != '\0') {
        ++i;
    }
    return i;
}

So... If you're REALLY worried about strings NOT being null-terminated then you'd do something like:

  • string[sizeof(string)]='\0'; on local automatic strings (where the compiler "knows" the size of the string);
  • or string[SIZE_OF_STRING] for all other strings, where SIZE_OF_STRING is (most commonly) a #define'd constant, or a variable which you maintain specifically to store the current-SIZE (not length) of a dynamically allocated string.

And if you're REALLY, REALLY, REALLY worried about strings not being null-terminated (like you're dealing with "dirty" libary methods (like Tuxedo's ATMI for example) you ALSO "clear" your "return strings" before passing them to the suspect library methods with:

  • before:memset(string, NULL, SIZE_OF_STRING);
  • invoke: DirtyFunction(/*out*/string);
  • after: string[SIZE_OF_STRING]='\0'

SIG11's are a complete biatch to find because (unless you "hook" them with a signal-processor and say otherwise, they cause Unix to hard-terminate your program, so you can't log anything (after the fact) to help figure out where-in-the-hell-did-that-come-from... especially considering that in many cases the line of code which throws the SIG11 is no-where-near the actual cause of the string loosing its null-terminator.

Does that make sense to you?

PS: WARNING: strncpy does NOT always null terminate... you probably meant strlcpy instead. I learned this the hard way... when a 60 million dollar billing run crashed.


EDIT:

FYI: Here's a "safe" (unoptimized) version of strlen which I'll call strnlen (I reckon this should be in string.h. Sigh.).

// retuns the length of the string (capped at size-1)
int strnlen(char *string, int size) {
    int i = 0;
    while( i<size && string[i]!='\0' ) {
        ++i;
    }
    return i;
}