Reading characters from a File with fscanf - c++

I have a problem, using fscanf function :(
I need to reed a sequence of characters from file like "a b c d" (characters are separated by space).
but it doesn't works :(
how I have to read them? (
I tried to print it and the result is uncorrect. I think, it's because of spaces. I really don't know why it doesn't work.
Tell me please, what is wrong with array access?

From cplusplus.com:
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). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
Then if your code is:
while ( fscanf(fin,"%c", &array[i++]) == 1 );
and your file is like this:
h e l l o
Your array will be:
[h][ ][e][ ][l][ ][l][ ][o]
If you change your code into:
while ( fscanf(fin," %c", &array[i++]) == 1 );
with the same file your array will be:
[h][e][l][l][o]
In any case the code works: it depends on what you want.
Anyway, you should think about starting to use fgets() + sscanf(), for example:
char buff[NUM];
while ( fgets(buff, sizeof buff, fin) )
sscanf(buff,"%c", &array[i++]);
With the single fscanf() the lack of buffer management can turns into buffer overflow problems.

Add white space before %c =>
while (fscanf(pFile," %c", &alpArr[i++]) == 1);
It should work.

Related

How to delimit this text file? strtok

so there's a text file where I have 1. languages, a 2. text of a number written in the said language, 3. the base of the number and 4. the number written in digits. Here's a sample:
francais deux mille quatre cents 10 2400
How I went about it:
struct Nomen{
char langue[21], nomNombre [31], baseC[3], nombreC[21];
int base, nombre;
};
and in the main:
if(myfile.is_open()){
{
while(getline(myfile, line))
{
strcpy(Linguo[i].langue, strtok((char *)line.c_str(), " "));
strcpy(Linguo[i].nomNombre, strtok(NULL, " "));
strcpy(Linguo[i].baseC, strtok(NULL, " "));
strcpy(Linguo[i].nombreC, strtok(NULL, "\n"));
i++;
}
Difficulty: I'm trying to put two whitespaces as a delimiter, but it seems that strtok() counts it as if there were only one whitespace. The fact there are spaces in the text number, etc. is messing up the tokenization. How should I go about it?
strtok treats any single character in the provided string as a delimiter. It does not treat the string itself as a single delimiter. So " " (two spaces) is the same as " " (one space).
strtok will also treat multiple delimiters together as a single delimiter. So the input "t1 t2" will be tokenized as two tokens, "t1" and "t2".
As mentioned in comments, strtok is also writes the NUL character into the input to create the token strings. So, it is an error to pass the result of string::c_str() as input to the function. The fact that you need to cast the constant string should have been enough to dissuade you from this approach.
If you want to treat a double space as a delimiter, you will have to scan the string and search for them yourself. Given you are using C APIs, you can consider strstr. However, in C++, you can use string::find.
Here's an algorithm to parse your string manually:
Given an input string input:
language is the substring from the start of input to the first SPC character.
From where language ends, skip over all whitespace, changing input to begin at the first non-whitespace character.
text is the substring from the start of input to the first double SPC sequence.
From where text ends, skip over all whitespace, changing input to begin at the first non-whitespace character.
Parse base, and parse number.

How to find the character "\" in a string?

I am trying to manipulate a string by finding the \ character in the string Find\inHere. However, I can't put that as an input in test.find('\', 0). It won't work and gives me the error "missing terminating character." Is there a way to fix test.find('\', 0)?
string test = "Find\inHere";
int x = test.find('\', 0); // error on this line
cout << x; // x should equal 4
\ is a character used to introduce special characters, for example \n newline, \xDB shows the ASCII character with hexadecimal number DB etc.
So, in order to search this special character, you have to escape it by adding another \, use:
test.find("\\",0);
EDIT : Also, in your first string, it is not written in it "Find\inHere" but "Find" and an error because \inHere isn't a special instruction. So, same way to avoid it, write "Find\\inHere".

For scanf(), why is negated scanset "%[^\n]" showing correct output for "\n", but not the scanset "%[aeiou]" for "aegis"?

In the following program, if I use the line for the negated scanset, it works fine if I enter a multi-word line (ending with ENTER or newline), even though the newline is in the negated list.
But if I use the line for the scanset instead and enter the word "aegis" (or any word with consonants for that matter), then junk characters are output. Analogous to the first case, shouldn't at least "ae" be output if I enter this word? Please explain this behavior of scanset and negated scanset for scanf().
#include <stdio.h>
int main ()
{
char str[30];
printf("Enter the string\n");
//scanf("%[^\n]",str);
//scanf("%[aeiou]",str);
printf("%s",str);
}
It is because code errantly does not check the return value of scanf()
printf("Enter the string\n");
scanf("%[^\n]",str);
scanf("%[aeiou]",str); // check result before using `str`
printf("%s",str);
With scanf("%[^\n]",str); and input like "123\n", str get the values of "123" and '\n' remains in stdin. Then with scanf("%[aeiou]",str); and input like "aegis\n", the first line's '\n' blocks saving anything as '\n' is not a vowel, nothing is saved in str and since code did not check the return value of scanf(), does not realized that str may be invalid.
1) Always check the return value of scanf() and family.
if (scanf(some_format, var1, var2, ...) != ExpectedConversionCount) {
Fail();
}
2) scanf("%[^\n]",str); to read a line fails 3 things: No input limit, fails to read anything if the the line consists of only '\n'. Without check the return value, EOF is not detected.
3) Use fgets() instead of scanf() for user input.

Print a string like "First\nSecond" on two lines

Aim: to read a string in the form First\nSecond from a file and to print it as
First
Second
Problem: if the string is defined in the code, as in line = "First\nSecond";, then it is printed on two lines; if instead I read it from a file then is printed as
First\nSecond
Short program illustrating the problem:
#include "stdafx.h" // I'm using Visual Studio 2008
#include <fstream>
#include <string>
#include <iostream>
void main() {
std::ifstream ParameterFile( "parameters.par" ) ;
std::string line ;
getline (ParameterFile, line) ;
std::cout << line << std::endl ;
line = "First\nSecond";
std::cout << line << std::endl ;
return;
}
The parameters.par file contains only the line
First\nSecond
The Win32 console output is
C:\blabla>SOtest.exe
First\nSecond
First
Second
Any suggestion?
In C/C++ string literals ("...") the backslash is used to mark so called "escape sequences" for special characters. The compiler translates (replaces) the two characters '\' (ASCII code 92) followed by 'n' (ASCII code 110) by the new-line character (ASCII code 10). In a text file one would normally just hit the [RETURN] key to insert a newline character. If you really need to process input containing the two characters '\' and 'n' and want to handle them like a C/C++ compiler then you must explicitely replace them by the newline character:
replace(line, "\\n", "\n");
where you have to supply a replace function like this:
Replace part of a string with another string (Standard C++ does not supply such a replace function by itself.)
Other escape sequences supported by C/C++ and similar compilers:
\t -> [TAB]
\" -> " (to distinguish from a plain ", which marks the end of a string literal, but is not part of the string itself!)
\\ -> \ (to allow having a backslash in a string literal; a single backslash starts an escape sequence)
The character indicated in a string literal by the escape sequence \n is not the same as the sequence of characters that looks like \n!
When you think you're assigning First\nSecond, you're not. In your source code, \n in a string literal is a "shortcut" for the invisible newline character. The string does not contain \n - it contains the newline character. It's automatically converted for you.
Whereas what you're reading from your file is the actual characters \ and n.

Tokenize a string based on quotes

I am trying to read data from a text file and split the read line based on quotes. For example
"Hi how" "are you" "thanks"
Expected output
Hi how
are you
thanks
My code:
getline(infile, line);
ch = strdup(line.c_str());
ch1 = strtok(ch, " ");
while (ch1 != NULL)
{
a3[i] = ch1;
ch1 = strtok(NULL, " ");
i++;
}
I don't know what to specify as delimiter string. I am using strtok() to split, but it failed. Can any one help me?
Please have a look at the example code here. You should provide "\"" as delimiter string to strtok.
For example,
ch1 = strtok (ch,"\"");
Probably your problem is related with representing escape sequences. Please have a look here for a list of escape sequences for characters.
Given your input: "Hi how" "are you" "thanks", if you use strtok with "\"" as the delimiter, it'll treat the spaces between the quoted strings as if they were also strings, so if (for example) you printed out the result strings, one per line, surrounded by square brackets, you'd get:
[Hi how]
[ ]
[are you]
[ ]
[thanks]
I.e., the blank character between each quoted string is, itself, being treated as a string. If the delimiter you supplied to strtok was " \"" (i.e., included both a quote and a space) that wouldn't happen, but then it would also break on the spaces inside the quoted strings.
Assuming you can depend on every item you care about being quoted, you want to skip anything until you get to a quote, ignore the quote, then read data into your input string until you get to another quote, then repeat the whole process.