Reading float numbers from a file in a special manner - c

I'm trying to read numbers from the file in a 2D-Array, i have to skip the first row and first column, rest all have to save in an array, i've tried using sscanf, fscanf and even strtok() but failed miserably. So please help me to solve this issue.
Thanx in advance,
Link to the file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char* argv[]){
FILE *f=fopen("Monthly_Rainfall_Himachal.txt","r");
float data[12][12];
int i,j;
char newLine[1000];
fgets(newLine,1000,f);
char* item,waste;
i=0;
while(1)//read file line by line
{
fscanf(f, "%s %f %f %f %f %f %f %f %f %f %f %f %f ", waste, &data[i][0], &data[i][1], &data[i][2], &data[i][3], &data[i][4], &data[i][5], &data[i][6], &data[i][7], &data[i][8], &data[i][9], &data[i][10], &data[i][11]);
i++;
if(feof(f))break;
}
fclose(f);
for(i=0 ;i<12 ;i++){
for(j=0 ;j<12 ;j++){
printf("%.1f\t",data[i][j]);
}
printf("\n");
}
return 0;
}

Problems:
You don't check if the fopen was successful in opening the file or not and blindly assume it did.
Check its return value:
if(f == NULL)
{
fputs("fopen failed! Exiting...\n", stderr);
return EXIT_FAILURE;
}
Instead of reading and storing the first line, you can just read and discard it using scanf:
scanf("%*[^\r\n]"); /* Discard everything until a \r or \n */
scanf("%*c"); /* Discard the \r or \n as well */
/* You might wanna use the following instead of `scanf("%*c")`
if there would be more than one \r or \n
int c;
while((c = getchar()) != '\n' && c != '\r' && c != EOF);
But note that the next fscanf first uses a `%s` which
discards leading whitespace characters already. So, the
`scanf("%*c");` or the while `getchar` loop is optional
*/
You have an unused character pointer item and a character variable waste. Both of these are unnecessary. So, remove them.
In the very long fscanf line, you first try to scan in a string into a character variable which invokes Undefined Behavior and things go haywire. You also need to check its return value to see if it was successful.
Replace that fscanf line with the following:
if(fscanf(f, "%*s") == EOF)
{
fputs("End Of File! Exiting...\n", stderr);
return EXIT_SUCCESS;
}
for(j = 0; j < 12; j++)
{
if(fscanf(f, "%f", &data[i][j]) != 1)
{
fputs("End Of File or bad input! Exiting...\n", stderr);
return EXIT_SUCCESS;
}
}
You assume the input is of a maximum of 12 lines, but if it contains more than 12 lines, your code will invoke Undefined Behavior due to an array overrun.
Check the value of i along with the feof to make sure it does not go beyond 11:
if(i >= 12 || feof(f))
Note: I did not test any of the above code. Please correct me if I've made a mistake. Thanks!

Related

Clang-Tidy: 'fscanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead

Somewhat unexperienced with C here!
I'm using CLion to write a program and keep getting this warning message whenever I use fscanf to store a value from an input file into a variable:
Clang-Tidy: 'fscanf' used to convert a string to an integer value, but
function will not report conversion errors; consider using 'strtol'
instead
I don't understand this error as I thought fscanf was the function I should be using to read input files? Can someone explain (at a noob level) what's wrong with the way I'm using it?
Here's a sample of my code:
FILE *initial_configuration_box_1_pointer;
initial_configuration_box_1_pointer = fopen("initial_configuration_box_1.xyz", "r");
fscanf(initial_configuration_box_1_pointer, "%d\n", &N1); // Warning here.
fscanf(initial_configuration_box_1_pointer, "pid\tx\ty\tz\n"); // No warning here.
for (i = 1; i <= n1; i++)
{
fscanf(initial_configuration_box_1_pointer, "p\t%lf\t%lf\t%lf\n", &rx1[i - 1], &ry1[i - 1], &rz1[i - 1]); // Warning here.
}
fclose(initial_configuration_box_1_pointer);
I'm aware similar questions have been asked, but I couldn't understand any of the (few) answers they got...
There are a lot of good reasons for a beginner to avoid scanf completely. (Read http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html). If you're going to use it interactively, never end a format string with whitespace, since doing so will just confuse the user. And always check the value returned by scanf to see if it actually matched any input. A common error is for the input to fail to match the expected data, and the scanf loop becomes an infinite loop repeatedly checking the same invalid input. Perhaps the warning is suggesting the second point above: since scanf does not validate the input for you, you have to do it explicitly by checking how many conversion specifiers scanf was able to match. Try something like:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char ** argv)
{
int n1;
const char *path = argc > 1 ? argv[1] : "initial_configuration_box_1.xyz";
FILE *ifp;
if( (ifp = fopen(path, "r")) == NULL ){
perror(path);
return EXIT_FAILURE;
}
if( 1 != fscanf(ifp, "%d", &n1) || n1 <= 0 ){
fprintf(stderr, "Invalid input\n");
return EXIT_FAILURE;
}
fscanf(ifp, " pid x y z");
double rx1[n1];
double ry1[n1];
double rz1[n1];
for( int i = 0; i < n1; i++ ){
if( 3 != fscanf(ifp, " p %lf %lf %lf", rx1 + i, ry1 + i, rz1 + i) ){
fprintf(stderr, "Invalid input near line %d\n", i);
return EXIT_FAILURE;
}
}
if( fclose(ifp) ){
perror(path);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Note that whitespace in a scanf format string does not match exactly, so using \n or \t or is all the same. Usually, people just use a single space to make it easier to read. Also, whitespace between certain conversion specifiers (notable %d and %lf) is irrelevant, and only included for readability.

Having problems transferring data from my second txt file to my second character array using command line arguments

The exact problem that I am having is that we were assigned to make a program that had 2 command line arguments, both being text files. The code that I have for arg[1] works fine, it reads in the text file and stores it into an array. Once it is stored into the array called key it goes through a loop that only leaves alpha characters and makes uppercase change to lowercase. Once again this works fine when i test it and print out the final array called key. When I use the same code for arg[2] the first loop (while(!feof(file2))) does not even copy the contents of the other text file into the array called plain correctly. It copies all the content but adds ā–’ at the end when i print out the plain array to test to see if I have all the characters in there before running it through the loop that only leaves alphacharacters in it. If I switch the order of the files when I enter them in the terminal then the second file works fine with the arg[1] code but then the other file does not work with the arg[2] code. I'm using mobaxterm so I enter it like "./a.out k1.txt p1.txt" without the quotations of course. I also commented out the code that strips the nonalpha characters in arg[2] just to try and figure out why the while loop before it is not storing the file contents correctly.
Here are the contents of the text files
k1.txt (instead of a space imagine it goes to the next line):
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
bbbbbbbbb
p1.txt:
"If you find that you're spending almost all your time on theory, start turning some attention to practical things; it will improve your theories. If you find that you're spending almost all your time on practice, start turning some attention to theoretical things; it will improve your practice." - Donald Knuth
This is an encryption assignment by the way and k1 is the key and p1 is the plain text.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char **argv) {
printf( "\ncommandline arguments including program name:\n\n");
int i;
for ( i = 0; i < argc; i++ ) {
printf( "argument %d: %s\n", i, argv[ i ] );
}
printf( "\n");
char* fname = argv[ 1 ];
FILE *file = fopen( fname, "r" );
char key[512];
int x,y, z=0;
if ( file == 0 )
{
printf( "Could not open file\n" );
} else {
printf( "File opened successfully\n" );
while(!feof(file))
{
fscanf(file, "%c", &key[z]);
z++;
}fscanf(file, "%c", &key[z]);
for(x=0; key[x] != '\0'; x++)
{
while(!((key[x] >= 'a' && key[x] <= 'z') || (key[x] >= 'A' && key[x] <= 'Z') || key[x] == '\0'))
{
for(y=x; key[y] != '\0'; ++y)
{
key[y]=key[y+1];
}
key[y] = '\0';
}
key[x] = tolower(key[x]);
}
printf("Key text:\n%s\n", key);
fclose( file );
}
char* fname2 = argv[ 2 ];
FILE *file2 = fopen( fname2, "r" );
char plain[512];
int j,k, l=0;
if ( file2 == 0)
{
printf("Could not open file\n");
}else {
printf("File opened successfully\n");
while(!feof(file2))
{
fscanf(file2, "%c", &plain[l]);
l++;
}fscanf(file2, "%c", &plain[l]);
/* for(j=0; key[j] != '\0'; j++)
{
while(!((plain[j] >= 'a' && plain[j] <= 'z') || (plain[j] >= 'A' && plain[j] <= 'Z') || plain[j] == '\0'))
{
for(k=j; plain[k] != '\0'; ++k)
{
plain[k]=plain[k+1];
}
plain[k] = '\0';
}
plain[j] = tolower(plain[j]);
}*/
printf("Plain text:\n%s\n", plain);
fclose(file2);
}
return 0;
}
feof
Check end-of-file indicator
Checks whether the end-of-File indicator associated with stream is set, returning a value different from zero if it is.
This indicator is generally set by a previous operation on the stream that attempted to read at or past the end-of-file.
Notice that stream's internal position indicator may point to the end-of-file for the next operation, but still, the end-of-file indicator may not be set until an operation attempts to read at that point.
[emphasis mine]
Now, lets see the how this loop will work:
while(!feof(file))
{
fscanf(file, "%c", &key[z]);
z++;
}fscanf(file, "%c", &key[z]);
Assume that fscanf() has read the last character of file. After this, the stream internal position indicator is pointing to EOF but feof() will return 0 because there is no read operation attempted on the stream which will set the end-of-file indicator. Hence the control go inside the loop and fscan() will attempt to read from file. Since EOF is reached, fscan() will set the end-of-file indicator. Now the EOF is set, so the feof() will return non-zero value and loop will end. Hence, the way you are using feof(), you will always have this extra iteration of while loop.
After encountering EOF, you are still trying to read from stream file:
fscanf(file, "%c", &key[z]);
Here, also fscanf() will return the EOF because there is nothing remain to read from stream file. This statement is meaning less.
In C, strings are actually one-dimensional array of characters terminated by a null character \0. fscanf() does not automatically append null character at the end when you read from stream using %c format specifier. So, the character array key and plain does not have null character at the end of characters read and if you try to print them using %s, you may get some junk character's in the output.
You can do:
while ((ret = fscanf(file, "%c", &key[z])) != EOF) {
z++;
}
key[z] = '\0';
You can also read the string of characters from file using %s format specifier, like this:
fscanf(file, "%511s", key);
With %s format specifier you dont need loop and a terminating null character is automatically added at the end of the stored sequence.
It is good to add check for max character modifier that is 1 less than the length of the input buffer (which is 511, in your case).
Alternatively, you can also use fgets() to read from file.
Check this:
while ( !feof (file) ) is always wrong?
Reading from file using fgets

How to check if user enters blank line in scanf in c

I need the program to exit the while loop if the user presses enter without entering any float value. Thanks!
printf("Enter scores\nā€);
float scores[10];
int n=0;
while (n<10){
scanf("%f", &scores[n]);
n++;
if (THE USER PRESSES ENTER WITHOUT ENTERING ANYTHING){break;}
}
You can use fgets() to read a line of input through the newline character into a buffer, and then use sscanf() to parse the contents of the buffer. The problem with using scanf() for this is that most conversion specifiers, and in particular the %f conversion specifier, skip leading whitespace, including newlines. So, if you try to give an empty line to scanf(), the function will continue to wait for input until you enter a non-white-space character.
The code below adapts this technique to your code. The variable n has been changed to a size_t type variable, as this is an unsigned type guaranteed to be able to hold any array index. Furthermore, note that both fgets() and sscanf() return values that should be checked. The fgets() function returns a null pointer if there is an error, and the code below prints an error message and exits if this occurs. The sscanf() function returns the number of successful conversions made, and this value can be used to make sure that the input is as expected. When the user enters a blank line, or a line with no leading floating point value (leading white-space is OK), zero is returned, and the input loop is escaped.
I added some code to display the values entered into the array.
#include <stdio.h>
#include <stdlib.h> // for exit()
int main(void)
{
float scores[10];
char buffer[100];
size_t n = 0;
printf("Enter scores\n");
while (n < 10){
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
fprintf(stderr, "Error in fgets()\n");
exit(EXIT_FAILURE);
}
if (sscanf(buffer, "%f", &scores[n]) == 1) {
++n;
} else {
break;
}
}
for (size_t i = 0; i < n; i++) {
printf("scores[%zu] = %f\n", i, scores[i]);
}
return 0;
}
Sample interaction:
Enter scores
3.8
3.6
2.9
3.4
scores[0] = 3.800000
scores[1] = 3.600000
scores[2] = 2.900000
scores[3] = 3.400000
Separate input of user text from parsing.
Read the line of user input as a string;
char buffer[80];
if (fgets(buffer, sizeof buffer, stdin) == NULL) Handle_EOF();
Now, parse the string using sscanf(), strtod(), etc.
if (sscanf(buffer, "%f", &scores[n]) == 1) Handle_Successful_Float_Input(scores[n]);
else if (buffer[0] == '\n') Handle_Empty_Line();
else Handle_Everything_Else(buffer);
fgets is the better route but if scanf must be used, newline can be detected by scanning a character. If the character is not a newline, replace it in the input with ungetc and then scan the float.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 10
int main ( void) {
char i = '\0';
int n = 0;
int result = 0;
float scores[SIZE] = { 0.0f};
printf ( "enter scores\n");
while ( n < SIZE && ( scanf("%c",&i) == 1)) {//scan a character
if ( i == '\n') {
break;//newline so leave loop
}
else {
ungetc ( i, stdin);//replace the character in input stream
}
if ( ( result = scanf ( "%f", &scores[n])) == 1) {//scan a float
printf ( " score[%d] entered as %f\n", n, scores[n]);
n++;
}
if ( result == 0) {
printf ( "please enter a number\n");//could not scan the input as a float
}
while ( ( result = getchar ( )) != '\n') {//clean the input stream
if ( result == EOF) {
fprintf ( stderr, "problem EOF\n");
return 1;
}
}
printf ( "enter score[%d]\n", n);
}
return 0;
}
I thought . you want to check that if an integer is assigned a value or not ?
Actually you have to initialize the variable otherwise it will contain whatever happen at that memory location unless it is declared as global. If you are not getting then check
this might help you with your question
We know that scanf returns a negative value if nothing of the defined type is fetched from the input.
So:
printf("Enter scores\nā€);
float scores[10];
int n=0;
while (n<10){
if(scanf("%f\n", &scores[n]) < 0) printf("Error! Error!");
n++;
}
See http://www.cplusplus.com/reference/cstdio/scanf/

C - reading ints and chars into arrays from a file

I have a .txt file with values written in this format: LetterNumber, LetterNumber, LetterNumber etc (example: A1, C8, R43, A298, B4). I want to read the letters and the numbers into two separate arrays (example: array1 would be A C R A B; array2 would be 1 8 43 298 4). How can I make it happen?
At the moment I only figured out how to read all the values, both numbers and letters and the commas and everything, into one array of chars:
FILE *myfile;
myfile = fopen("input1.txt", "r");
char input[677]; //I know there are 676 characters in my .txt file
int i;
if (myfile == NULL) {
printf("Error Reading File\n");
exit (0);
}
for (i=0; i<677; i++) {
fscanf(myfile, "%c", &input[i]);
}
fclose(myfile);
But ideally I want two arrays: one containing only letters and one containing only numbers. Is it even possible?
I would appreciate any kind of help, even just a hint. Thank you!
Define another array for integers,
int inputD[677];
Then in for loop read one char, one integer and one space char at a time.
fscanf(myfile, " %c%d %*[,] ", &input[i], &inputD[i]);
I would actually define a struct to keep letter and number together; the data format strongly suggests that they have a close relation. Here is a program that exemplifies the idea.
The scanf format is somewhat tricky to get right (meaning as simple as possible, but no simpler). RoadRunner, for example, forgot to skip whitespace preceding the letter in his answer.
It helps that we have (I assume) only single letters. It is helpful to remember that all standard formats except %c skip whitespace. (Both parts of that sentence should be remembered.)
#include<stdio.h>
#define ARRLEN 10000
// Keep pairs of data together in one struct.
struct CharIntPair
{
char letter;
int number;
};
// test data. various space configurations
// char *data = " A1, B22 , C333,D4,E5 ,F6, Z12345";
void printParsedPairs(struct CharIntPair pairs[], int count)
{
printf("%d pairs:\n", count);
for(int i = 0; i<count; i++)
{
printf("Pair %6d. Letter: %-2c, number: %11d\n", i, pairs[i].letter, pairs[i].number);
}
}
int main()
{
setbuf(stdout, NULL);
setbuf(stdin, NULL);
// For the parsing results
struct CharIntPair pairs[ARRLEN];
//char dummy [80];
int parsedPairCount = 0;
for(parsedPairCount=0; parsedPairCount<ARRLEN; parsedPairCount++)
{
// The format explained>
// -- " ": skips any optional whitespace
// -- "%c": reads the next single character
// -- "%d": expects and reads a number after optional whitespace
// (the %d format, like all standard formats except %c,
// skips whitespace).
// -- " ": reads and discards optional whitespace
// -- ",": expects, reads and discards a comma.
// The position after this scanf returns with 2 will be
// before optional whitespace and the next letter-number pair.
int numRead
= scanf(" %c%d ,",
&pairs[parsedPairCount].letter,
&pairs[parsedPairCount].number);
//printf("scanf returned %d\n", numRead);
//printf("dummy was ->%s<-\n", dummy);
if(numRead < 0) // IO error or, more likely, EOF. Inspect errno to tell.
{
printf("scanf returned %d\n", numRead);
break;
}
else if(numRead == 0)
{
printf("scanf returned %d\n", numRead);
printf("Data format problem: No character? How weird is that...\n");
break;
}
else if(numRead == 1)
{
printf("scanf returned %d\n", numRead);
printf("Data format problem: No number after first non-whitespace character ->%c<- (ASCII %d).\n",
pairs[parsedPairCount].letter, (int)pairs[parsedPairCount].letter);
break;
}
// It's 2; we have parsed a pair.
else
{
printf("Parsed pair %6d. Letter: %-2c, number: %11d\n", parsedPairCount,
pairs[parsedPairCount].letter, pairs[parsedPairCount].number);
}
}
printf("parsed pair count: %d\n", parsedPairCount);
printParsedPairs(pairs, parsedPairCount);
}
I was struggling a bit with my cygwin environment with bash and mintty on a Windows 8. The %c would sometimes encounter a newline (ASCII 10) which should be eaten by the preceding whitespace-eating space, derailing the parsing. (More robust parsing would, after an error, try to read char by char until the next comma is encountered, and try to recover from there.)
This happened when I typed Ctr-D (or, I think, also Ctr-Z in a console window) in an attempt to signal EOF; the following enter key stroke would cause a newline to "reach" the %c. Of course text I/O in a POSIX emulation on a Windows system is tricky; I must assume that somewhere between translating CR-NL sequences back and forth this bug slips in. On a linux system via ssh/putty it works as expected.
You basically just have to create one char array and one int array, then use fscanf to read the values from the file stream.
For simplicity, using a while loop in this case makes the job easier, as you can read the 2 values returned from fscanf until EOF.
Something like this is the right idea:
#include <stdio.h>
#include <stdlib.h>
// Wasn't really sure what the buffer size should be, it's up to you.
#define MAXSIZE 677
int
main(void) {
FILE *myFile;
char letters[MAXSIZE];
int numbers[MAXSIZE], count = 0, i;
myFile = fopen("input1.txt", "r");
if (myFile == NULL) {
fprintf(stderr, "%s\n", "Error reading file\n");
exit(EXIT_FAILURE);
}
while (fscanf(myFile, " %c%d ,", &letters[count], &numbers[count]) == 2) {
count++;
}
for (i = 0; i < count; i++) {
printf("%c%d ", letters[i], numbers[i]);
}
printf("\n");
fclose(myFile);
return 0;
}

Reading first line by getchar() in c

I want to read first line by getchar() but compiler tell me that array A is int type. How can I save my first line char by char in array using getchar?
#include <stdio.h>
int main(void) {
FILE *fp;
int i=0;
char A[200];
int c;
fp = fopen("input.txt", "r");
while ((c=getchar()) != '\n') && i<200) {
A[i]=(char)c;
i++;
}
for(i=0; i<200; i++) {
printf("%s", A[i]);
}
}
Your reading is (almost) fine, the biggest issue is printing.
Before fixing it, though, you should change the call of getchar to fgetc(fp) - something you probably meant to do, because you used fopen.
If you would like to print your line character-by-character, you need to use %c instead of %s format specified, ans stop iterating when you reach the length of the string that you have read. The %s specifier is also fine, as long as you null-terminate your string. It lets you avoid the loop, too:
A[i] = '\0';
printf("%s\n", A);
With printing out of the way, here are a few other things that you need to fix:
Allocate an extra char for null terminator:
char A[201];
You could also stop reading upon reaching character 199 in your loop.
Make sure that the program stops reading when you reach EOF:
while ((c=fgetc(fp)) != '\n') && c != EOF && i<200) {
...
}
As dasblinkenlight said, the %s specifier is used for strings while the %c is used for char. Therefore, your print statement should be
printf("%c\n",A[I]);
To ensure that the file has not ended, you could also use
!feof(fp)
in your while loop. If the file you were reading from contained less than 200 characters, you would run into problems. The feof function checks for the end of the file to ensure you wont read data after the file is ended.
you can give it a try with something like this
#include <stdio.h>
int main(void)
{
FILE *fp;
int i=0;
char A[200];
int c;
fp = fopen("input.txt", "r");
while ((c=getchar()) != '\n' && i<200 )
{
A[i]=(char)c;
i++;
};
for(int j=0; j<i; j++) // print only those item available in array
{
printf("%c", A[j]);
}
}

Resources