-3

I'm new to FILE I/O Stream and I want to write a program, which converts chars (read from "texti.txt") like "ä,Ä,ü,Ü,ö,Ö" to "ae,Ae,ue,Ue,oe,Oe" and write them in a new file called "texto.txt".

First Question: Is it ok to have two file pointers (on to each file) at the same time like i do?

Second Question: What am I doing wrong with character compare in the switch statement? VS2015 is warning that cases 2 and 3 already exist (reference to case 1)

Thirt Question Does fpo (file pointer to output-file) increment itself automatically by writig a char?

Question four: VS2015 is warning:

C4996 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

Is there another function I should use?

int main()
{
    char c;
    FILE *fpi;
    FILE *fpo;
    fpi = fopen("texti.txt","r");
    fpo = fopen("texto.txt", "w");
    if (fpi == NULL)
        fprintf(stderr, "Fehler beim Lesen");
    while (!feof(fpi))
    {
        c = fgetc(fpi);
    switch (c)

{
    case 'ä'||'Ä':      
        fputc('a', fpo);
        fputc('e', fpo);
        break;

    case 'ö'||'Ö':
        fputc('o', fpo);
        fputc('e', fpo);
        break;

    case 'ü' || 'Ü':
        fputc('u', fpo);
        fputc('e', fpo);
        break;

    default:
        fputc((c), fpo);
    }
    fpi++;
}
fclose(fpi);
fclose(fpo);

}

A.Lymphater
  • 73
  • 1
  • 11
  • 3
    What do you think, will `fpi++;` do? Also, `c` should be an `int` and you don't check the result of your second `fopen`. – pzaenger Jan 20 '16 at 14:25
  • One question at a time. – Karoly Horvath Jan 20 '16 at 14:25
  • 3
    `foef` does [not work](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) as you apparently expect. Also be careful with non-ASCII character encodings. It is well possible this does not work as expected. At least you need `char16_t` or `char32_t` fort this. – too honest for this site Jan 20 '16 at 14:25
  • You can have multiple file pointers pointing to their own files, no problem. But these pointers do not point directly into the file, so you do not increment them. They point to information the OS maintains about the file and within there is information about current file location. You don't need to mess with it. You would use file I/O functions on the file pointer to get information you need like current location, etc. – lurker Jan 20 '16 at 14:28
  • Oh, and your case labels do also not work like that. Summarising the flaws of your code, you really should consult a good C book or tutorial. You seem to have some missconception of the basics. – too honest for this site Jan 20 '16 at 14:28
  • 2
    You need to read [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – Some programmer dude Jan 20 '16 at 14:33
  • @lurker: so does fgetc(fpi) return the next Char, everytime I call it? – A.Lymphater Jan 20 '16 at 14:36
  • @Danny_ds: The letters are there, just sort them at your will. I think it is still clear what the typo means. (Btw. I cannot find a translation of that word. Slang?) – too honest for this site Jan 20 '16 at 14:38
  • 1
    @classMate yes it does. It will continue to do so until you see an EOF (which you get on a read after you have read the last character, which i swhy your use of `feof` is not proper - `feof` is only true after you have read an EOF, which is one read too late for your loop). Internally, the control information for the open file (pointed to by the FILE pointer) is updated automatically and keeps track of where you are. You might want to Google search "file I/O in C" for some examples. – lurker Jan 20 '16 at 14:41
  • @Danny_ds: Sorry, there seems to be no translation (tried some via google). I suspect that is some slang. – too honest for this site Jan 20 '16 at 14:43

2 Answers2

2

There are really to many different questions there, you should concentrate on one at a time, and post different questions if they are distinct like yours.

I'll answer the second question, about the switch statement. And the answer is if you want to use multiple values in a single case, you can't. You can however rely on the fact that cases fall through down if there is no break statement, and then you can do e.g.

switch (c)
{
case 'ä':
case 'Ä':
    // Code for the ä or Ä case
    break;

...
}

You could also use tolower or toupper:

switch (tolower(c))
{
case 'ä':
    // Code for the ä or Ä case
    break;

...
}

A little explanation about what is wrong with case 'ä'||'Ä'.

What happens is that the compiler sees 'ä' || 'Ä' as a boolean expression, and in C everything non-zero is considered true. Also in C boolean true is considered to be equal to 1, which means that the expression in your cases are equal to 1 || 1 which is true and therefore 1, so all your cases are case 1.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

You can have as many open file pointers as you wish (limited by the maximum amount of open files a process can have, but in most modern OSes this number runs into the thousands). You should remember to close them all, though.

As for "incrementing" file pointers, remember that, despite the type is called FILE *, this doesn't actually point to the contents of the file, it points to an internal management structure that <stdio.h> uses to handle files. Therefore, something like fpi ++ is not updating the internal file position pointer (which is what you want to do); it's simply making fpi point to some other FILE structure. While there are legitimate reasons to do this (e.g., pointers to arrays of FILE *), moving inside the file is not done this way.

If you actually need to move inside a file, there's a function called fseek() that does this. However, reads or writes (i.e., calls to fread(), fwrite(), fgets(), fprintf(), getc() (and its equivalent fgetc()), putc() (and its equivalent fputc()), and any other function you can imagine that performs I/O on files represented by FILE * values) already update the internal file pointer to point after the data that the operation handled. In other words, when you read or write a character, the internal file pointer will already point after that character. You don't need to, and you shouldn't, attempt to update it yourself, since it's already been done for you.

The character comparisons will probably fail due to encodings — while there is a pretty standard way of representing the usual ASCII characters (codepoints 32 to 126; basic letters, numbers, and so on), international characters don't have this luxury. You'll need to find out what encoding the file uses, and handle that encoding manually; probably by using the raw character numbers instead of character notation. There are also wide character functions to help you here, if you want to research into that. EDIT: I just noticed your 'C' || 'c' notation in the case labels. That simply evaluates to 1, as any constant expression in a case label is solved at compile time (and non-constant ones aren't allowed at all). You need multiple case labels to match multiple values; you cannot use expressions there.

Finally, the VS warning is spurious, as fopen() is a standard library call. Do remember to #include the appropriate file, though (in this case <stdio.h>).

aaaaaa123456789
  • 5,541
  • 1
  • 20
  • 33
  • So could I compare Chars with its ASCII-code ? Like: if(c==66) {} – A.Lymphater Jan 20 '16 at 14:54
  • 1
    You can do that (and in fact, in virtually every relevant platform, it's identical to `if (c == 'B') { /* something */ }`), but keep in mind that you need to know the exact codepoint. ASCII goes up to 127; after that it's no man's land (because every vendor fills the 128-255 space in a different way) unless you know the exact encoding of the text you're handling. (At any rate, remember that `char` is a numeric type, and therefore any operations valid on numbers are valid on `char`.) – aaaaaa123456789 Jan 20 '16 at 15:07