How to write a string in a stream using physical files?

Asked

Viewed 1,084 times

6

When inserting in a text file the characters of a string in C, blank spaces are ignored. How should I make long sentences within a string have separate words?

Follows the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
    int op = 10, k;
    char str[100], c, arquivo[20];
    FILE *fluxo;
    do{
        printf("Digite:\n1- Criar arquivo\n2- Inserir no arquivo\n3- Ler arquivo\n4- Fechar fluxo\n5- Remover arquivo");
        scanf("%d",&op);
        switch(op){
            case 1:
                printf("\nDigite o nome do arquivo: \n");
                scanf("%s",arquivo);
                fluxo = fopen(arquivo,"w");
                if(!fluxo)
                    printf("\n***Erro ao abrir/criar arquivo!***\n");
            break;
            case 2:
                printf("\nDigite o texto a ser gravado:\n");    
                scanf("%s",str);
                for (k=0;str[k];k++){
                    c = str[k];
                    putc(c, fluxo);
                }
                    //fprintf(fluxo, "%s",str);             
            break;
            case 3:
                fclose(fluxo);
                fluxo = fopen(arquivo, "r");
                while(!feof(fluxo)){
                    fscanf(fluxo,"%c", &c);
                    printf("%c",c);
                }
            break;
            case 4:
                fclose(fluxo);
            break;
            case 5:
                remove(arquivo);
            break;
        }
    }while(op!=0);
    fclose(fluxo);

}
  • 2

    I think your problem is not time to write the file, but time to read. scanf reads a string up to the first blank.

  • It is not the scanf, because the file when I open the target file, it is also without spaces, with all words concatenated.

  • 1

    Notice that you’re giving fscanfin loop. At each fscanf you read a string, up to the space, and put it in the file. But the spaces are ignored, this is normal of the scanf/fscanf. If your goal is to copy from one file to another, it is best to use freadand fwrite.

  • 1

    The @C.E.Gesser is right. It is better to use the fgets.

2 answers

5

According to the function documentation scanf:

Whitespace Character: the Function will read and ignore any whitespace characters encountered before the next non-whitespace Character (whitespace characters include Spaces, newline and tab characters -- see isspace).

Freely translating:

"White character: the function will read and ignore any white character found before the next non-white character (white characters include space, new line and tab)."

What happens then is that your reading is being "broken" in the text spaces. Assuming the test "This is a test." the first reading will simply return "This", and the rest will be kept in the stream to return in the next readings "eh", "um" and "test." respectively.

I figured you could include a blank space between each reading, but @C.E.Gesser well recalled that there is no way to know if there are one or more spaces between words. Therefore, I believe that the ideal is to use the fgets indicating the stdin as a source for reading and the maximum size of the data buffer:

fgets(str, 100, stdin);
  • 1

    fgets is indeed the best alternative. Manually placing the spaces after will not work, because there is no way to know if it was one or more spaces between the words.

  • @C.E.Gesser True. I will edit to correct this suggestion. :)

3

The problem is that the scanf("%s",str); reads the string and ignores whitespace. A solution to this is " %[^\n]", instead of %s, which will read the entire line written by the user until it finds a character \n, including the spaces.

scanf(" %[^\n]", arquivo);

Or

scanf("%[^\n]%*c", arquivo);

This second adds a %*c to suppress the ENTER that the user will give to confirm the end of the string (reference).


In the test I did here with your code, I also changed the scanf("%d",&op); for scanf("%d%*c",&op); for the ENTER after typing the index, "swallow" the chosen options.


Note: Consider using fgets instead of scanf, if possible. When using scanf, should be attentive to some details to avoid overflow (as presented here).

  • 1

    Cool solution! But I think it’s worth giving a read on the disadvantages of scanf (http://stackoverflow.com/questions/2430303/disadvantages-of-scanf). :)

  • 1

    @Luizvieira Interesting link. There is a lot to consider when you will use scanf. Anyway, it is good to present this solution because sometimes it has to use scanf even.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.