For my homework, I have to read data from an input file and to store it in a double dimensional array and then pass this array to another function. This is what I have tried so far, but I don't know when I call this function in main it gives the error:
Access violation writing location 0x00000000.
I have tried to dynamically allocate memory and it gives the same error. What I am doing wrong?
The last update of the code:
#include<stdio.h>
#include<stdlib.h>
int *a[2];
void getData(void)
{
FILE *fp = fopen("input.txt", "r");
int number;
fscanf(fp, "%d", &number);
for (int i = 0; i < number; i++)
{
a[i]=(int*)malloc(number * sizeof (int));
fscanf(fp, "%d %d", &a[i][0], &a[i][1]);
}
fclose(fp);
}
int main()
{
getData();
for(int i=0;i<8;i++)
{
printf("%d %d\n",a[i][0],a[i][1]);
}
}
You need to allocate memory for a
Before the for loop
a = (int **)malloc(number * sizeof(int *))
You are not allocating the first dimension, ie a is a null pointer when you are trying to dereference it.
#include <stdlib.h>
a = malloc(number * sizeof *a);
BTW, sizeof(int) is not sufficient to store two numbers.
#include <stdlib.h>
a[i] = malloc(2 * sizeof *a[i]);
fscanf(iFile, "%d %d", &a[i][0], &a[i][1]);
Here is a whole correct code (although not perfect, as long as a is an hugly global variable):
int (*a)[2] = NULL;
void getData(void)
{
FILE *fp = fopen("input.txt", "r");
int number;
fscanf(fp, "%d", &number);
a = malloc(number * sizeof *a);
for (int i = 0; i < number; i++)
fscanf(fp, "%d %d", &a[i][0], &a[i][1]);
fclose(fp);
}
Related
I was hoping to get a bit of help, I am implementing an inversion counter algorithm to take in 50,000 intergers and display the inversions and time it took to run the algorithm, I am having a hard time allocating and saving the integers from the file into an array. My code complies and runs but nothing happens
here is what I have:
int main(int argc, char** argv)
{
int n, i;
int inversions=0;
int *A;
FILE *file;
char filename[100];
clock_t start, end;
double totalTime;
printf("Enter filename: ");
scanf("%s", filename);
file = fopen(filename, "r");
if(file == NULL)
{
printf("Error opening file!\n");
return 0;
}
fscanf(file, "%d", &n);
A = (int*) malloc(n * sizeof(int));
for(i = 0; i < n; i++) {
fscanf(file, "%d", &A[i]);
}
start = clock();
inversions = countInversionsBruteForce(A, n);
end = clock();
totalTime = (double) (end - start) / CLOCKS_PER_SEC;
printf("Brute Force Algorithm\n");
printf("Number of inversions: %d\n", inversions);
printf("Execution time: %f\n", totalTime);
I think I have noth allocated array size and saved it properly
Your program is incomplete so I was not able to compile it. Minimized the problem to just loading the data into your array:
Formatted code for readability.
Generated a suitable input file. Most likely this is your problem but you have not shared your input sample with us.
Added missing include files.
Remove argc, argv as you not using them.
Minimize scope of variables. Use size_t instead of int for unsigned values.
Max string size on obtaining file name
Check return value for scanf(), fopen(), fscanf().
Printing out the data read to demonstrate it's working.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
printf("Enter filename: ");
char filename[100];
if(scanf("%99s", filename) != 1) {
printf("scanf failed\n");
return 1;
}
FILE *file = fopen(filename, "r");
if(!file) {
printf("Error opening file!\n");
return 1;
}
size_t n;
fscanf(file, "%zu", &n);
if(!n) {
printf("n must be positive");
return 1;
}
int *A = malloc(n * sizeof(*A));
for(size_t i = 0; i < n; i++)
if(fscanf(file, "%d", &A[i]) != 1) {
printf("fscanf() failed\n");
return 1;
}
printf("n = %zu\n", n);
printf("A = ");
for(size_t i = 0; i < n; i++)
printf("%d%s", A[i], i + 1 < n ? ", " : "\n");
}
with 1.txt as:
4
1
2
3
4
a sample session looks like this:
Enter filename: 1.txt
n = 4
A = 1, 2, 3, 4
So I have a file format that designates the first line of the file to be the number of students total in the file and the next lines are the students with their information(Student ID, Grade, GPA). Formatted like this:
30
1320 A 3.9
1200 B 3.3
1250 F 0.0
When I am reading in the data into arrays I am not getting the correct info and I'm not sure if its because of how I'm directly reading it in my fscanf or I'm not skipping to the next line. But all thats being stored is random basically random data from memory.
void file_sort(char *infile, char *outfile)
{
FILE *fp;
fp = fopen(infile, "r");
int num;
fscanf(fp, "%d%[^\n]", &num);
int *student_id;
student_id = (int*) malloc (num * sizeof(int));
char *grade;
grade = (char*) malloc (num * sizeof(char));
double *gpa;
gpa = (double*) malloc (num * sizeof(double));
printf("\n%d", num);
for(int i = 0; i < num; i++)
{
fscanf(fp, "%d, %c %f%[^\n]", &student_id[i], &grade[i], &gpa[i]);
}
}
So to answer my own question my issue was in worrying about going to the next line while reading the file I created my own problem by include the
"%[^\n]"
This code below functions properly for anyone coming back to this problem.
void file_sort(char *infile, char *outfile)
{
FILE *fp;
fp = fopen(infile, "r");
int num;
fscanf(fp, "%d", &num);
printf("\n%d", num);
int *student_id;
student_id = (int*) malloc (num * sizeof(int));
char *grade;
grade = (char*) malloc (num * sizeof(char));
double *gpa;
gpa = (double*) malloc (num * sizeof(double));
printf("\n%d", num);
for(int i = 0; i < num; i++)
{
fscanf(fp, "%d %c %lf", &student_id[i], &grade[i], &gpa[i]);
}
}
First, you need to give the filename, and then for reading the GPA (double) value you need to use %lf, also there is an extra ',' after the %d. The following code fixed all these bugs. Hopes it help
FILE *fp;
fp = fopen('YOUR FILE NAME', "r");
int num;
fscanf(fp, "%d%[^\n]", &num);
printf("\n%d", num);
int *student_id;
student_id = (int*) malloc (num * sizeof(int));
char *grade;
grade = (char*) malloc (num * sizeof(char));
double *gpa;
gpa = (double*) malloc (num * sizeof(double));
printf("\n%d", num);
for(int i = 0; i < num; i++)
{
fscanf(fp, "%d %c %lf%[^\n]", &student_id[i], &grade[i], &gpa[i]);
}
I am struggling with reading floats from a file which I created during the program lifetime. I was trying to rewind the file, I was trying to open and close file before reading it, I was trying to put values directly in the table and by another variable. Idk what can I do more, what's wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
float *tab;
float x = 0.0;
int i, size;
FILE *fp;
fp = fopen("data.txt", "w+");
if (fp == NULL) {
printf("Error");
system("PAUSE");
exit(1);
}
printf("Size of table: ");
scanf("%d", &size);
tab = (int*)malloc(size * sizeof(int));
for (i = 0; i < size; i++) {
tab[i] = (8.0 - 2.0) * (float)rand() / RAND_MAX + 2.0;
fprintf(fp, "%.2f ", tab[i]);
}
for (i = 0; i < size; i++) {
printf("%.2f ", tab[i]);
}
printf("\n");
fp = fclose;
fp = fopen("data.txt", "w+");
tab = realloc(tab, 2*size);
for (i = 0; i < size * 2; i+=2) {
fscanf(fp, "%f", &x);
printf("%.2f ", x);
//tab[i + 1] = tab[i] / 2;
}
/*for (i = 0; i < size * 2; i++) {
printf("%.2f \n", tab[i]);
}*/
fp = fclose;
printf("\n");
system("PAUSE");
return 0;
}
There are a number of problems in this code. First, as noted in the comments, the initial allocation is wrong. You are allocating space for floats, not ints. You could have avoided this problem entirely if you had written the call to malloc() like this:
tab = malloc(sizeof(*tab) * size);
Here, the result of malloc() is not cast, since it is not necessary in C. Also, note that instead of using an explicit type for the argument to the sizeof operator, the identifier is used instead. This guarantees that whatever the type of tab, which must be a pointer, the result of sizeof will be correct. Also, you should always check to see if an allocation was successful.
fp = fclose is just wrong. This should be fclose(fp). After this, when you open the file again with "w+", the file is truncated to zero length, and you lose the data that was previously written. Since the file has already been opened with "w+", just use rewind(fp) here.
For the reallocation that you do, aside from that the arguments are not quite right here, there is a potential problem that you should be aware of. realloc() can return a null pointer in the event of an allocation error. If this happens, and you are directly assigning the result of realloc() to the pointer for which you are reallocating (tab), then you will lose the reference to previously allocated memory. This is a memory leak, and lost data. The way to do this is to store the result of realloc() in a temporary pointer, which you test. If the temporary pointer is a null pointer, there was an error; otherwise you can safely assign the return value to the original pointer.
And as already noted, when you call fclose() the final time, it needs to be fclose(fp).
Here is a modified code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL));
float *tab, *temp; // added temp for realloc() check
float x = 0.0;
int i, size;
FILE *fp;
fp = fopen("data.txt", "w+");
if (fp == NULL) {
printf("Error");
system("PAUSE");
exit(1);
}
printf("Size of table: ");
scanf("%d", &size);
/* You should always check for allocation errors */
if ((tab = malloc(sizeof(*tab) * size)) == NULL) {
fprintf(stderr, "Error in initial allocation\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < size; i++) {
tab[i] = (8.0 - 2.0) * (float)rand() / RAND_MAX + 2.0;
fprintf(fp, "%.2f ", tab[i]);
}
for (i = 0; i < size; i++) {
printf("%.2f ", tab[i]);
}
printf("\n");
// fclose(fp); // not fp = fclose;
// fp = fopen("data.txt", "w+"); // when you reopen, the file is truncated
rewind(fp); // but just do this
/* Fixed this reallocation */
temp = realloc(tab, sizeof(*tab) * size * 2);
if (temp == NULL) {
fprintf(stderr, "Error in reallocation\n");
exit(EXIT_FAILURE);
}
tab = temp;
for (i = 0; i < size * 2; i+=2) {
fscanf(fp, "%f", &x);
printf("%.2f ", x);
//tab[i + 1] = tab[i] / 2;
}
/*for (i = 0; i < size * 2; i++) {
printf("%.2f \n", tab[i]);
}*/
fclose(fp); // not fp = fclose;
printf("\n");
system("PAUSE");
return 0;
}
Sample interaction:
Size of table: 10
2.65 5.67 5.21 3.22 3.07 4.29 5.96 5.96 5.15 7.36
2.65 5.67 5.21 3.22 3.07 4.29 5.96 5.96 5.15 7.36
Reading a file, first number is an int that's the size of the array, then the rest are double
Here is the function:
void read1dascii(double** a, int* m, char* infile)
{
FILE * fp = fopen(infile, "r");
fscanf(fp, "%d", m);
alloc1d(a, *m);
fscanf(fp, "%lf\n", *a);
fclose(fp);
}
Here is the alloc1d function it calls:
void alloc1d(double** a, int m)
{
*a = malloc(sizeof(double) * m);
}
I'm getting the first number which is the size and then the first number in array, but then the rest are reading in as zeros.
You need to read all of them using loop.
int i;
for (i = 0; i < *m; ++i) {
fscanf(fp, "%lf", *a + i);
}
fscanf(fp, "%lf\n", *a);
Here you are only reading once, so it's just receiving the first float, to read the rest of the array, you need something like
while ( fscanf(fp, "%lf\n", &a) == 1 )
{
/* do stuff with 'a' here */
}
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
float** getdata(void);
void calculations(float* fPtr);
//void printoriginal(float* values, int inputnum, float* fPtr);
int main(void)
{
float** fPtr;
float* values;
fPtr = getdata();
calculations(*fPtr);
int element;
// printoriginal(*values, inputnum, *fPtr);
system("PAUSE");
return 0;
}
float getvalues(void)
{
float* values = (float*)calloc(*inputnum, sizeof(float));
float** getdata(void)
{
int i;
int n;
float** fPtr;
int* inputnum;
printf("How many values do you want to input into the array?");
scanf("%d", inputnum);
float* values = (float*)calloc(*inputnum, sizeof(float));
if (values == NULL)
{ printf("Memory overflow\n");
exit(101);
}
for(i = 0; i < *inputnum; i++)
{
n = i + 1;
printf("Please enter your %d number: ", n);
scanf("%f",(values+i));
}
fPtr = (float**)calloc(*inputnum+1, sizeof(float*));
if (fPtr == NULL)
{ printf("Memory overflow\n");
exit(101);
}
for(int c=0; c < *inputnum; c++)
{
*(fPtr+i) = (values+i);
}
printf("%f", values+2);
return fPtr;
}
I scanf the values in getdata, but I am scanning in garbage. Im pretty certain my scanf is off. Also, how would I be able to pass back my values array through reference?? I am having a very hard time with that as well. Thanks everyone.
Instead of
int * inputnum;
scanf( ..., inputnum );
you want:
int inputnum;
scanf( ..., &inputnum );
Either that, or you need to insert an allocation of inputnum:
/* Very non-C-worthy code sample */
int * inputnum;
inputnum = malloc( sizeof *inputnum );
if( inputnum == NULL ) {
perror( "malloc" );
exit( EXIT_FAILURE );
}
scanf( ..., inputnum );
but that will look very strange to anyone familiar with C
(Unless there is some other reason for it, and in this
case there does not appear to be any reason.)
The problem you are experiencing is that the scanf is
storing the received value in the location pointed to
by inputnum, which is a bogus location since inputnum
is uninitialized.
I like to have objects "assigned" to one single function. In your program, your values are created in the function getdata(), used in calculations() and never released.
If the main() function was responsible for them, it would make coding easier, in my opinion. Something like
int main(void) {
int inputnum, innum;
double *fPtr;
printf("How many values do you want to input into the array?");
fflush(stdout);
if (scanf("%d", &inputnum) != 1) {
fprintf(stderr, "Error in input. Program aborted.\n");
exit(EXIT_FAILURE);
}
if (inputnum > MAX) { /* ... nothing yet ... */ }
fPtr = calloc(inputnum, sizeof *fPtr);
if (fPtr == NULL) {
fprintf(stderr, "Not enough memory. Program aborted.\n");
exit(EXIT_FAILURE);
}
/* use fPtr in other functions */
innum = data_get(fPtr, inputnum);
data_print(fPtr, innum);
free(fPtr);
return 0;
}
In the snippet above, I used the functions data_get() and data_print() with a somewhat different prototype than you have. These functions take a pointer and a number of elements.
int data_get(double *data, int num);
void data_print(double *data, int num);
The first one reads up to num doubles into the memory pointed to by data and returns the number of doubles that was effectively entered.
The second takes number of doubles to print.
Oh! Unless you have a very good reason to use floats, don't use them. Always prefer doubles.
Also Instead of
printf("%f", values+2);
use
printf("%f", *(values+2));
There is so many errors, I didn't know where to start :)
Code completely rewritten below. Please study this.
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
int get_data (float** array); /* must be pointer-to-pointer to return through parameter */
void print_data (const float* array, int size); /* print data */
void do_weird_things (float* array, int size); /* do weird things with the data */
void clear_data (float* array); /* clean up */
int main(void)
{
float* array;
int size;
size = get_data (&array);
printf("Before weird things:\n");
print_data (array, size);
do_weird_things (array, size);
printf("After weird things:\n");
print_data (array, size);
clear_data (array);
system("PAUSE");
return 0;
}
int get_data (float** array)
{
int i;
int items;
printf("How many values do you want to input into the array? ");
scanf("%d", &items);
getchar(); /* remove \n from stdin */
*array = calloc(items, sizeof(float));
if (*array == NULL)
{
printf("Memory overflow\n");
exit(EXIT_FAILURE);
}
for(i = 0; i < items; i++)
{
printf("Please enter your %d number: ", i+1);
scanf("%f", (*array) + i);
getchar(); /* remove \n from stdin */
}
return items;
}
void do_weird_things (float* array, int size) /* do whatever data manipulation you wish here */
{
int i;
for(i=0; i<size; i++)
{
array[i] += i;
}
}
void print_data (const float* array, int size)
{
int i;
for(i=0; i<size; i++)
{
printf("%f\t", array[i]);
}
printf("\n");
}
void clear_data (float* array)
{
free(array);
}