2

I write the following code to write a text. strcmp is supposed to terminate the file writing when the user type #. Still doesn't do it and i cannot exit the program

#include <stdio.h>
#include <string.h>
int main()
{
    FILE *fp;
    char c[100];
    fp = fopen ("/home/smksx/Desktop/uniprograms/domes/arxeio2","w");
    printf ("\n\nWrite your text\n\n");
    printf ("\n\nTerminate with #\n\n");
    while (strcmp(c,"#")!=0)
        {
        scanf ("%s",&c);
        if (strcmp(c,"#")!=0)
            {
            fprintf (fp,"%s",c);
        }
    }
    fclose(fp);
    return 0;
}
smksx
  • 47
  • 5

4 Answers4

2

you have several issues in your code:

  1. c is pointer to char, so you may not use & in scanf

  2. your while loop is checkin uninitialized data

  3. scanf reads up to the \n, and not adding it to the file

here's what you code could look like:

#include <stdio.h>
#include <string.h>
int main()
{
    FILE *fp;
    char c[100];
    fp = fopen ("/home/smksx/Desktop/uniprograms/domes/arxeio2","w");
    printf ("\n\nWrite your text\n\n");
    printf ("\n\nTerminate with #\n\n");
    while (1) // c is not initialized, so do not check it's content here
    {
        scanf ("%s",c);        // c is pointer to char, so no & here
        if (strcmp(c,"#")!=0)  // here c is safe to be checked
        {
            fprintf (fp,"%s\n",c);  // you may be adding a \n here
        }
        else 
            break;     // do not repeat yourself: no need to double strcmp
    }
    fclose(fp);
    return 0;
}
Tommylee2k
  • 2,683
  • 1
  • 9
  • 22
1

If strcmp is not giving the desired results, try strchr to find a #.
Use the precision field, %.*s, to print up to the #. The asterisk allows for an variable precision as one of the arguments to printf.
If word by word processing is preferred over line by line, swap the comment on the while statements to use scanf instead of fgets.

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

int main ( void) {
    char input[100] = "";
    char *find = NULL;

    //while ( 1 == scanf ( "%99s", input)) {//process word by word, no spaces
    while ( fgets ( input, sizeof input, stdin)) {
        input[strcspn ( input, "\n")] = 0;//remove newline
        if ( ( find = strchr ( input, '#'))) {//find a # in input
            if ( find != input) {//not the first character
                printf ( "%.*s\n", (int)(find - input), input);//print up to #
            }
            break;
        }
        else {
            printf ( "%s\n", input);//did not find #
        }
    }

    return 0;
}
user3121023
  • 8,181
  • 5
  • 18
  • 16
0

There some problems in your code:

  1. You cannot use '&' when getting input char array (i.e. string). You have to use scanf("%s", c) instead.

  2. As scanf "ignores" spaces, I would recommend you to use fgets. So your final code can be:

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

int main()
{
    FILE *fp;
    char c[100] = { 0 }; // init to empty string

    fp = fopen("out.txt", "w");
    printf("\n\nWrite your text\n\n");
    printf("\n\nTerminate with #\n\n");

    while (strcmp(c, "#") != 0)
    {
        fgets(c, sizeof(c), stdin);

        if (strcmp(c, "#\n") != 0) //fgets includes new line character too
            fprintf(fp, "%s", c);
    }

    fclose(fp);
    return 0;
}

fgets function reads whole line of text (without danger of overflow), so it is easier than scanf

Moreover, I would not recommend you to use full path when creating file, because, in other systems, it might fail (I had to change it under Windows)

Miradil Zeynalli
  • 423
  • 4
  • 18
  • 3
    Please do not recommend `gets`. It is no longer a standard C function, see [Why is the gets function so dangerous that it should not be used?](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) At least with `scanf` you can restrict the input length, for example `scanf ("%99s", c);` – Weather Vane Feb 25 '20 at 13:48
  • 4
    It isn't suitable *at all*: it is obsolete , and `fgets` is better. – Weather Vane Feb 25 '20 at 13:50
  • 1
    But from a security point of view, `gets()` is as good (bad) as `scanf("%s", ...)`. – Ctx Feb 25 '20 at 13:58
  • 1
    Unlike `scanf` the length restriction for `fgets` *includes* the nul terminator. Also, the string won't be equal to `"#"` until the newline is removed. Please see [Removing trailing newline character from fgets() input](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221) – Weather Vane Feb 25 '20 at 14:01
  • Off by 1. `fgets(c, 100, stdin);` is OK. `fgets(c, sizeof c, stdin);` better. – chux - Reinstate Monica Feb 25 '20 at 16:15
0

Initially in the condition of the loop

while (strcmp(c,"#")!=0)

there is used uninitialized variable c. So the program has undefined behavior. In this call of the function scanf

scanf ("%s",&c);

the type of the second argument is incorrect. The type of the expression &c is char ( * )[100] while the function expects that the second argument has the type char *.

Also you should check 1) whether the file was opened successfully and 2) the user does not interrupt the input in the array.

Instead of the scanf that reads until a white space is encountered when the conversion specifier %s is used it is much better to use the standard function fgets.

Also if you are writing to a text file then it is desirable to append each record with the new line character.

The main part of the program can look the following way.

if ( fp != NULL )
{
    while ( fgets( c, sizeof( c ), stdin ) != NULL && strcmp( c, "#" ) != 0 )
    {
        fprintf ( fp, "%s", c );
    } 
}

Pay attention to that fgets appends the new line character to the entered string provided that the string with the new line character can be accommodated in the character array.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335