C fscanf discarding extra characters if there is any
I'm working on this project for one of my classes and it states, "Discard everything after the three digit characters up to and including the next newline or EOF".
For example, the following would be a example test configuration file:
119
3561234
263abc
I need to save the first three digit characters to individual variables defined as row, column, value (respectively).
The code I have so far is the following:
/*
* Read in the initial puzzle configuration.
* Each line is 4 characters long:
* Row as a character '0' .. '9'
* Column as character '0' .. '9'
* Digit as character '0' .. '9'
* Terminating newline.
* Exits with an error message if there are syntactic
* or semantic errors with any configuration line.
*/
void configure(FILE *puzzle_file) {
int row, column, value; // Variables
int count = 1; //the counter for what line we are on
/*
* Loops through every line transforming the chars to character int values
* for each int needed and addes it to puzzle and changes fixed values
* at same location.
*/
while((fscanf(puzzle_file, "%1i%1i%1i%*[^\n]", &row, &column, &value)) != EOF){
if(!in_range(row) || !in_range(column) || !in_range(value)){
printf("Illegal format in configuration file at line %i\n", count);
exit(1);
}
if(puzzle[row][column] != 0){
printf("Illegal placement in configuration file at line %i\n",count);
exit(1);
}
puzzle[row][column] = value;
fixed[row][column] = 1;
count++;
}
}
I would expect that 9 would go in row 1 and column 1, 6 go in row 3 and column 5, and 3 would go in row 2 and column 6.
With a prop开发者_StackOverflow社区er formated config file it will go into the first if statement and end there.
Proper config file example:
123
356
235
etc..
I'm assuming its my fscanf thats making it not work correctly. How would you change that so it would do that?
EDIT 1:
in_range function:
/*
* Return TRUE iff the value is in the Sudoku range (1 .. 9)
*/
static bool in_range(int value) {
if(isdigit(value) && value != 0){
return TRUE;
}
return FALSE;
}
It would appear you think fscanf()
uses regular expressions.
It doesn't. C doesn't have regular expressions.
I think you're looking for:
fscanf(puzzle_file, "%1i%1i%1i%*s", &row, &column, &value)
This will grab the 1st, 2nd, and 3rd characters as integers, then the remaining data on the line will not be stored in a variable.
I'd never seen [^/n]
in scanf, and apparently that's not the problem.
I suspect the problem is in your in_range()
function. What is that?
Edit since additional code was posted:
Your fscanf
was fine. Your in_range()
is not. isdigit()
tells you whether or not a character is a digit.
Re-reading your requirements, I suggest this for your line reading logic:
char buffer[5];
int row, column, value;
int count = 1;
while(fgets(buffer, 5, puzzleFile) != NULL)
{
if ( (buffer[3] == '\n')
&& (sscanf(buffer, "%1i%1i%1i%*[^\n]", &row, &column, &value) == 3))
{
puzzle[row][column] = value;
}
else
{
printf("Illegal format in configuration file at line %i\n", count);
exit(1);
}
count++;
}
This guarantees that each line is 3 characters with a newline. %1i
in sscanf guarantees that each character is a digit in the range of 0-9 if all three matched and were assigned to your variables (it returns the number of assignments).
Try reading a line at a time from the file into a buffer using something like getline()
. Then use
sscanf(buffer, "%1d%1d%1d", &row, &column, &value);
to scan the values into your variables.
精彩评论