I am currently working on the C code below. I need to access the array outside the while loop, after fclose. It appears that the blackfin ADSP kernel crashes every time I run it. I will need it further to perform FFT. Please help!
#include <stdlib.h>
#include <stdio.h>
#include <flt2fr.h>
#include <fract_math.h>
#include <math_bf.h>
#include <complex.h>
#include <filter.h>
int main()
{
int n = 1024;
long int dat1[n];
FILE *file1;
fract16 *m;
int i;
// file1 open and read the values
file1 = fopen("0.dat", "r");
if (file1 == NULL) {
printf("I couldn't open 0.dat for reading.\n");
exit(0);
}
while (!feof(file1)) {
fgets(dat1, n, file1);
m = malloc(sizeof(fract16) * n);
for (i = 0; i < n; i++) {
sscanf(dat1, "%f", &m[i]); //getting error here
}
}
fclose(file1);
printf("%lf\n", m);
return 0;
}
Alright, thank you all for correcting my mistakes, but the problem is still unresolved. I am able to print all of the values inside, but outside the loop it prints just the last value of the data set, is there any precise solution for this? I googled for hours but no success yet.
The code is as follows >
#include <stdlib.h>
#include <stdio.h>
#include <flt2fr.h>
#include<fract_math.h>
#include <math_bf.h>
#include <complex.h>
#include <filter.h>
int main()
{
int n = 1024;
long int dat1[n];
FILE *file1;
fract16 *m;
file1 = fopen("0.dat", "r");
if (file1 == NULL) {
printf("I couldn't open 0.dat for reading.\n");
exit(0);
}
while( !feof(file1))
{
fgets(dat1,n,file1);
sscanf(dat1, "%f", &m);
printf("%f\n",m); //Prints all elements in the 1st column of the array, 0.dat is a nx2 matrix
}
fclose(file1);
}
You can allocate memory for the buffer before reading the file, outside the while loop. Then every time before reading into the buffer, simply use memset and set the buffer to all null characters.
Also, try using fread to read directly into the buffer rather than fgets
the variable m is defined as a pointer to and array of fract16
to fix the problem suggest:
if( 1 != sscanf(dat1, "%f", m+(sizeof(fract16)*i) )
{
perror( "sscanf failed" );
exit( EXIT_FAILURE );
}
The error is being cause because m is already a pointer and you want it to continue to be a pointer
As an aside. the code is not checking how much data was actually read in the call to fgets() so the for() may very well be reading behond the end of the actual data. And each trip through the while() loop is destroying/overlaying the pointer obtained from the prior call to malloc()
then later in the code is the statement:
printf("%lf\n", m);
But m is a pointer to an array of `fract16 objects.
and those fract16 objects might be double values, but that detail is not clear. In any case, this call to printf() will, at best, only output a single double value from the beginning of the last line in the input file. Is that what you really want to do?
Note: dat1[] is declared as an array of long int, but the call to sscanf() seems to be trying to extract float values.
I.E. the code is not consistent about the data types, nor the extraction of individual values, nor the printing.
One thing to note: with the current code there is a massive memory leak due to the pointer m being repeatedly overwritten by the calls to malloc() And due to the use of feof(), the last call to fgets() will fail, so the cotents of dat1[] will be starting with a NUL byte
Suggest allocating an array of pointers to fractl16 objects
Then for each line read, use malloc() to set the next pointer in the array of pointers, ...
Related
I am kind of new when it comes to C. Took a class on it in college but I just don't practice it much. Well my issue that I'm having is that I'm trying to take an text file and convert it into an array. I have been able to get the text file and print it into the console but when I save run the while statement to read each line, my whole array gets overwritten. For instance if my last line on my text file is 19, my array[0] gets over written to what should be on array[18].
I know the indentations are off a off, coding is a mess, and forgive me on the printf commands, I'm only using them to troubleshoot my code. The text file will have IP address on each line.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#define MAX_LINE_LENGTH 16
int main()
{
int lineCntPOSlist = 0;
int lineCnt = 0;
int i = 0;
FILE *textfile;
char line[MAX_LINE_LENGTH];
char* posList[50];
textfile = fopen("pos-list.txt", "r");
if(textfile == NULL)
{
int posListExist = 0;
system("cls");
printf("File Exist %d\n", posListExist);
fprintf(stderr, "**File open failed\n Make sure there is a pos-list.txt file");
return 1;
}
system("cls");
while(fgets(line, MAX_LINE_LENGTH, textfile))
{
printf("Line %d: %s",lineCnt , line);
posList[lineCnt] = line;
printf("posList[%d] = %s\n", lineCnt, posList[lineCnt] );
printf("posList[0] = %s\n", posList[0] );
lineCnt = ++lineCnt;
lineCntPOSlist = ++lineCntPOSlist;
}
fclose(textfile);
return 0;
}
This:
posList[lineCnt] = line;
simply sets posList[lineCnt] to point at the line buffer in line, it copies zero characters of actual data. In higher-level languages where strings have a bit more presence, this would make sense, but in C it doesn't.
Since there is only one line buffer, it will always hold the characters making up the most recently loaded line, and thus it will act as if previous lines are being "overwritten".
There are several solutions, here are a few:
Make posList into a proper array of strings, but that requires you to decide max length in advance and will waste the space for shorter lines.
Use something like strdup() to allocate copies on the heap of each line, and store pointers to those.
Use a more "proper" reallocating array for the storage and store line pointers (or offsets, which might be better suited due to the reallocating) in the array for easier access.
So I gotta make this program that reads a huge .txt file into an AVL, and for that, I need to read all the formatted data in the text document and put it into an AVL. However, any time I try to initialize the AVL in my code (a NULL pointer) it breaks the code once it reaches the fscanf function I used to gather the strings out of the .txt file. I made this demo right here, and I think I'm pretty close to the source of the problem. I narrowed it down to being related to initializing a pointer with a NULL value before the fscanf function. But how do I fix this?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE * filePointer = fopen("_lexico_shuf.txt", "r");
if(!filePointer) {
printf("can't open the file");
exit(101);
}
char *lexiconWord;
float polarity;
int *a = NULL;
printf("before while");
while (!feof(filePointer)) {
fscanf(filePointer, "%[^;];%f\n", lexiconWord, &polarity);
printf("| (%s) (%.1f) |", lexiconWord, polarity);
}
printf("after while");
}
so the only thing that is printed on the screen is the "before while" printf, and not the "after while" one. and the program returns a random number.
lexiconWord hasn't been set to point anywhere, so fscanf is using an invalid pointer value to attempt to write to.
Change this variable to an array, and use a field width in fscanf do you don't overrun the buffer, and check the return value of fscanf.
char lexiconWord[100];
...
int rval = fscanf(filePointer, "%99[^;];%f\n", lexiconWord, &polarity);
if (rval != 2) {
printf("not all values read\n");
exit(1);
}
Also, see Why is “while ( !feof (file) )” always wrong?
This question already has answers here:
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 5 years ago.
I need to read in a line of text, store it into an array. When I compile the program, it works but then when I execute it, I receive a segmentation fault. I have read other questions and tried what they have suggested and nothing seems to be working.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
FILE *file;
char text[10000000], *line[10000000];
int i=0;
file = fopen("/home/Documents/xxxxxx_HW01/text.txt", "r");
if(file == NULL) {
printf("cannot open file");
exit(1);
}
while (i< 10000 && fgets(text, sizeof(text), file)!= NULL){
line[i] = strdup(text);
i++;
}
for (i=0; text[i] != '\0'; i++)
printf("%c ", text[i]);
fclose(file);
}
Continuing from my comment,
text[i] = strdup (text);
Is wrong. It attempts to assign a pointer (the result of strdup) to text[i] a signed char value. You need to use a separate array of pointers (or declare a pointer to pointer to char, e.g. char **lines; and then allocate pointers and then for each line).
The most important thing you can do is Listen to what your compiler is telling you. To make sure you are getting the benefit of your compilers help, always compile with warnings enabled and do not accept code until it compiles without warning. For gcc that means adding at minimum -Wall -Wextra to your compile string. For clang, -Weverything will do. For cl.exe (VS) add /Wall. Then read and understand the warnings. The compiler will give you the exact line where any problem occurs.
If you are simply reading lines less than some number, you can avoid allocating pointer and just use an array of pointers, but you must keep track of the index (to avoid writing beyond the last element)
Based on what you are attempting, it looks like you are trying to do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1000
int main (void) {
FILE *file;
char text[MAX] = "",
*lines[MAX] = {NULL};
int i=0, j;
file = fopen ("/home/Documents/xxxxxx_HW01/text.txt", "r");
if(file == NULL) {
printf("cannot open file");
exit(1);
}
while (i < MAX && fgets (text, sizeof(text), file)!= NULL){
size_t len = strlen (text); /* get length */
if (len && text[len-1] == '\n') /* check if last is '\n' */
text[--len] = 0; /* overwrite with '\0' */
else { /* line too long - character remain unread */
fprintf (stderr, "error: line exceeds %d chars.\n", MAX - 2);
exit (EXIT_FAILURE);
}
lines[i] = strdup(text);
i++;
}
for (j = 0; j < i; j++) {
printf ("line[%3d] %s\n", j, lines[j]);
free (lines[j]); /* don't forget to free memory */
}
fclose(file);
return 0; /* main() is type int and therefore returns a value */
}
note: you should also remove the trailing '\n' included at the end of text by fgets -- example given above.
Look things over and let me know if you have further questions.
From what I remember sizeof will give you the size of the object type, and the fgets expects the maximum amount of chars you want to read, so you probably don’t want to use sizeof there.
Also you are increasing the index of your array indefinitely which is most likely going to give you a out of bounds exception.
Summing up I think you should try passing directly the size you set on your array on the fgets, and if you dont need the file to be all stored at the same time, just don’t increase i and handle each chunk in one iteration of the loop. If you do need the file all stored at once, make sure you have an array as big as your file size and perhaps use fread like this
I am trying to take input with fgets(). I know how many lines I will get but it changes and I store the number of lines in the variable var. I also have another variable named part; it is the length of the line I get, but since there are white spaces between the values I multiplied it by 2 (I couldn't find another solution; I could use some advice).
Anyway, I tried to get the input as in the code below, but when I entered the first line it automatically breaks out the for loop and prints random things. I think it is to do with the fgets() in the loop; I don't know if there is a use of fgets() like this.
char inp[var][(2*part)];
int k,l;
for(k=0;k<=var;k++);
fgets(inp[k],(2*part),stdin);
printf("%c\n",inp[0]);
printf("%c\n",inp[1]);
printf("%c\n",inp[2]);
printf("%c\n",inp[3]);
…since there are white spaces between the values I multiplied it with 2…
If you aren't required to store everything on the stack, you can instead store the strings in dynamically allocated memory. For example:
char* inp[var];
char buf[400]; // just needs to be long
for (k = 0; k < var; k++) {
fgets(buf, 400, stdin);
inp[k] = malloc(sizeof(char) * (strlen(buf) + 1));
strcpy(inp[k], buf);
}
Although technically not standards-compliant, strdup is widely available and makes this easier as well.
As far as the actual issue, as BLUEPIXY said in the comments above, you have a few typos.
After the for loop, the semicolon makes it act unexpectedly.
for(k=0;k<=var;k++);
fgets(inp[k],(2*part),stdin);
is actually the same as
for(k=0;k<=var;k++) {
; // do nothing
}
fgets(...);
Remove that semicolon after the for loop statement. As it is, you're not actually reading correctly, which is why you see garbage.
To print an entire string, the printf family needs a %s format flag.
With your bounds on k, there will actually be var + 1 iterations of the loop. If var were 3, then k = 0,1,2,3 -> terminate when k checked at 4.
Typically, the safest and easiest way to use fgets is to allocate a single, large-enough line buffer. Use that to read the line, then copy it into correctly sized buffers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
// Allocate just the space for the list, not the strings themselves.
int num_input = 5;
char *input[num_input];
// Allocate our reusable line buffer.
char line[1024];
for( int i = 0; i < num_input; i++ ) {
// Read into the line buffer.
fgets(line, 1024,stdin);
// Copy from the line buffer into correctly sized memory.
input[i] = strdup(line);
}
for( int i = 0; i < num_input; i++ ) {
printf("%s\n",input[i]);
}
}
Note that strdup() is not an ISO C function, but POSIX. It's common and standard enough. It's too handy not to use. Write your own if necessary.
That takes care of not knowing the line length.
If you don't know the number of lines you're storing, you'll have to grow the array. Typically this is done with realloc to reallocate the existing memory. Start with a small list size, then grow it as needed. Doubling is a good rough approximation that's a pretty efficient balance between speed (reallocating can be slow) and memory efficiency.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(void) {
// How big the input list is.
size_t input_max = 64;
// How many elements are in it.
size_t input_size = 0;
// Allocate initial memory for the input list.
// Again, not for the strings, just for the list.
char **input = malloc( sizeof(char*) * input_max );
char line[1024];
while( fgets(line, 1024,stdin) != NULL ) {
// Check if we need to make the input list bigger.
if( input_size >= input_max ) {
// Double the max length.
input_max *= 2;
// Reallocate.
// Note: this is only safe because we're
// going to exit on error, otherwise we'd leak
// input's memory.
input = realloc( input, sizeof(char*) * input_max );
// Check for error.
if( input == NULL ) {
fprintf(stderr, "Could not reallocate input list to %zu: %s", input_max, strerror(errno) );
exit(1);
}
}
input[input_size] = strdup(line);
input_size++;
}
for( size_t i = 0; i < input_size; i++ ) {
printf("%s\n",input[i]);
}
}
As you can see, this gets a bit complicated. Now you need to keep track of the array, its maximum size, and its current size. Anyone using the array must remember to check its size and grow it, and remember to error check it. Your next impulse will be to create a struct to collect all that together, and functions to manage the list.
This is a good exercise in dynamic memory management, and I encourage you to do it. But for production code, use a pre-existing library. GLib is a good choice. It contains all sorts of handy data structures and functions that are missing from C, including pointer arrays that automatically grow. Use them, or something like it, in production code.
I am attempting to read the size values from the header of a .pgm image file (mars.pgm), and assign the resulting values to the integer variables u and v using sscanf.
When executed the program prints P5 832 700 127 in the first line, which is correct (the 832 and 700 are the size values that I want to pick out).
In the second line that is meant to print u and v variables two very large numbers are printed, instead of the 832 and 700 values.
I cannot figure out why this is not working as desired. When using the small test program (located at the bottom of the post) sscanf picks out the values from a string like I expected it to.
#include<stdio.h>
#include <string.h>
int main()
{
FILE *fin;
fin= fopen ("mars.pgm","r+");
if (fin == NULL)
{
printf ("ERROR");
fclose(fin);
}
int u,v,i,d,c;
char test[20];
for (i=0; i<=20; i++)
{
test[i]=getc(fin);
}
sscanf(test,"%d,%d,%d,%d",&c,&u,&v,&d);
printf("%s\n",test);
printf("%d %d",u, v);
fclose(fin);
}
small test Program
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(void)
{
int a;
char s[3];
s[0]='1';
s[1]=' ';
s[2]='2';
sscanf(s,"%d",&a);
printf("%d",a);
}
First of all, I advise you to make a small test: initialize your variables with a 0, for instance, and verify what value they are holding after read operation.
Then, try removing , characters from your format string. Check if it works then.
This behavior you see is happening because fscanf() and derivatives match the full pattern when scanning, which means if your source data has no commas and your format has commas, it may be ignored.