Calloc/Malloc error - c

I am trying to write a program, but every time I try allocating memory, the 4th member of other array loses its meaning. Here is my code:
At first I read file with integer type numbers: In example. 1 2 3 1 2 3 1 2 3
int* reading (int* numbers, char* arg2[])
int* fuction(int* numbers);
int main(int arg1, char *arg2[] ){
if(arg1 != 2){return 0;}
int *numbers;
numbers = reading(numbers, arg2);
numbers = function(numbers);
return 0;
}
int* reading (int* numbers, char* arg2[]){
FILE *in=fopen(arg2[1], "r");
if (in == NULL) {
fprintf(stderr, "Can't open file !\n");
exit(1);
}
int data, length = 1;
numbers = (int*)malloc(3*sizeof(int));
while (fscanf(in, "%d", &data) != EOF){
numbers[length] = data;
length++;
numbers = realloc(numbers, length+1);
}
numbers[0] = length;
numbers[0]--;
return numbers;
}
int* fuction(int* numbers){
int sum = 0;
int i = 0;
int* places;
places = (int*)malloc(1*sizeof(int));
places[0] = 0;
for(i = 1; i <= numbers[0]; i++){ sum += numbers[i];}
if((((numbers[0]) % 3) > 0) || ((sum % ((numbers[0])/3)) > 0)){return places;}
sum = sum / ((numbers[0])/3);
int* newNumbers;
for(i = 1;i<=numbers[0];i++){printf("%d ", numbers[i]);}
printf("\n");
Here in cmd I see: 1 2 3 1 2 3 1 2 3
newNumbers = calloc(numbers[0]+1,sizeof(int) );
for(i = 1;i<=numbers[0];i++){printf("%d ", numbers[i]);}
printf("\n");
But after allocating memory for newNumbers(I tried both - malloc and calloc), I see result like this: 1 2 3 102506522 2 3 1 2 3
places = realloc(places, numbers[0]+1);
for(i = 1;i<=numbers[0];i++){printf("%d ", numbers[i]);}
printf("\n");
Here result stays the same: 1 2 3 102506522 2 3 1 2 3
}
Writing like this:
places = realloc(places, numbers[0]+1);
newNumbers = calloc(numbers[0]+1,sizeof(int) );
I mean allocating memory for "places" at first,
does not solve my problem as well. After:
newNumbers = calloc(numbers[0]+1,sizeof(int) );
I lose numbers[4]- meaning.
I can't understand why it is happening. Maybe someone could help me and give me an advice, how could I correct it.

Related

Realloc in C random int

I have a problem with reallocating memory of dynamically allocated array. So what i am trying to do is:
typedef struct {
int s;
int l;
int* arr;
bool orient;
}DAC;
...
int main()
{
DAC heap = {
4, 0, (int*)malloc(4 * sizeof(int))
};
char c = 0;
int n = 0;
while (1)
{
scanf("%c", &c);
switch (c)
{
case '+':
if (heap.s == heap.l)
{
heap.s *= 2;
heap.arr = (int*)realloc(heap.arr, heap.s);
}
scanf("%d\n", &(heap.arr[heap.l]));
heap.l++;
break;
case 'p':
for (int i = 0; i < heap.l; i++)
printf("%d ", heap.arr[i]);
printf("\n");
break;
}
}
}
As long as my whole structure works for n<5 (i start with array of size '4'), weird things happens when this block is executed:
if (heap.s==heap.l)
{
heap.s*=2;
heap.arr=(int*)realloc(heap.arr,heap.s);
}
What is the reason im getting wrong output at index [2] of my array?
I know i could do it with mallocs, just wondering as i think it is weird case
Whole input/output:
+ 1
+ 2
+ 3
+ 4
p
1 2 3 4
+ 5
p
1 2 -33686019 4 5
You start correct when you initialize heap:
DAC heap = {
4, 0, (int*)malloc(4 * sizeof(int))
};
But when you actually want to increase the size, you forget to adjust to the size of integers.
Instead of increasing the size to fit for 8 int values, you only get 8 bytes instead.
As Felix G reminded in a comment, you should never directly assign to the same pointer. If realloc returns NULL you have no more access to the old address.
Use this instead:
if (heap.s == heap.l)
{
heap.s *= 2;
void *tmp = realloc(heap.arr, heap.s * sizeof(int));
if (tmp != NULL) {
heap.arr = tmp;
} else {
// handle error...
}
}

I need help about arrays

Program Explain:
1/2/3
2 3 5
2 9 4
2 5 7
if i write 1in up it give me 2+9+7
if i write 2in up it give me 5+9+2
if i write 3in up it give me (2+9+7)-(5+9+2)
(BUT IT GIVES WARING:
* stack smashing detected *: unknown terminated
Aborted (core dumped)
)
#include <stdio.h>
#include <math.h>
int main()
{
int whatUDo;
int square[2][2];
int counter1 = 0, counter2 = 0, counter3 = 0;
int threeTime = 3;
scanf("%d", &whatUDo);
while (counter1 < 3)
{
scanf("%d", &square[0][counter1]);
counter1++;
}
while (counter2 < 3)
{
scanf("%d", &square[1][counter2]);
counter2++;
}
while (counter3 < 3)
{
scanf("%d", &square[2][counter3]);
counter3++;
}
int first = square[0][0] + square[1][1] + square[2][2];
int second = square[0][2] + square[1][1] + square[2][0];
int third = first - second;
if (whatUDo == 1)
{
printf("%d", first);
}
else if (whatUDo == 2)
{
printf("%d", second);
}
else if (whatUDo == 3)
{
printf("%d", third);
}
return 0;
}
TL;DR
The size of your array is wrong.
For the code you have provided, you have to declare your array as
int square[3][3];
Because the boundaries you are handling are from 0..2 and 0..2, respectively. The number you specify when declaring the array is the size, not the maximum index allowed.
In other way, if you declare:
int myarray[5];
The items of your array are accessed from 0 to 4, and your array has a capacity of 5 items accessed by the indices 0, 1, 2, 3 and 4.

Array dynamically allocated by file size is too large

I am working on a class assignment and need some help with dynamically allocated arrays. I am using file_size to try to pull the file size from 3 files to allocate the array to that size, then I need to write and sort the data in the array. My issue right now is with sizing of the array; right now my output (ignoring sorting) is:
1
3
7
9
0
0
0
0
2
4
8
0
0
0
5
6
10
0
0
0
0
0
0
As you can see it is being padded with extra 0s. Here are the input files:
inputFile1:
1
3
7
9
inputFile2:
2
4
8
inputFile3:
5
6
10
0
I need some help figuring out what's going on with this and where the issue is. I want to get rid of those extra 0s, and I'm not even sure where they are coming from. Help with the sorting would also be appreciated.
file_size:
long file_size(FILE *inputFile)
{
if(inputFile == NULL)
return -1;
long pos = ftell(inputFile);
fseek(inputFile, 0, SEEK_END);
long size = ftell(inputFile);
fseek(inputFile, pos, SEEK_SET);
return size;
}
Main:
int main(void)
{
FILE *file0 = fopen("list0.txt", "r");
FILE *file1 = fopen("list1.txt", "r");
FILE *file2 = fopen("list2.txt", "r");
FILE *output = fopen("hw3.out", "w");
long size0 = file_size(file0);
long size1 = file_size(file1);
long size2 = file_size(file2);
long totalSize = size0 + size1 + size2;
int *numbers = malloc(totalSize * sizeof(int));
int i;
int index = 0;
for(i = 0; i < file_size(file0); i++)
{
if(!feof(file0))
{
fscanf(file0, "%i", &numbers[index]);
index++;
}
else
break;
}
for(i = 0; i < file_size(file1); i++)
{
if(!feof(file1))
{
fscanf(file1, "%i", &numbers[index]);
index++;
}
else
break;
}
for(i = 0; i < file_size(file2); i++)
{
if(!feof(file2))
{
fscanf(file2, "%i", &numbers[index]);
index++;
}
else
break;
}
for(i = 0; i < totalSize; i++)
{
fprintf(output, "%i\n", numbers[i]);
}
fclose(file0);
fclose(file1);
fclose(file2);
fclose(output);
free(numbers);
return 0;
}
Your input files have several lines, each of which has the textual representation of a number. Your file size function however is counting the total number of bytes in the file. These are not the same.
While you can still use the file size to allocate space (you'll just get more than you need), you need to instead check the return value of scanf to see if a number was read. If not, you jump out of the loop.
int index = 0;
while (fscanf(file0, "%i", &numbers[index]) == 1) {
index++;
}
while (fscanf(file1, "%i", &numbers[index]) == 1) {
index++;
}
while (fscanf(file2, "%i", &numbers[index]) == 1) {
index++;
}
for(i = 0; i < index; i++)
{
fprintf(output, "%i\n", numbers[i]);
}
The size calculation includes the carriage return "\n" character at the end of the file. Therefore, you are allocating space for 8 integers for the first file, 6 integers for the second file and 10 integers for the third file (10, because the number "10" has two digits).
The correct allocation strategy would be not to count the bytes in the files, but the lines (which actually contain numbers, thus allowing you to skip empty lines).
But that's just too much trouble. Instead, consider just allocating 1000 bytes, read in until you run out, then re-alloc into a larger buffer.

How can I convert this "for" loop to use EOF in C?

char* readScores(int* actualCount) {
char* stringArray = (char*)malloc(100*sizeof(char));
for(int i = 0; i <= 13; i++) {
*actualCount = *actualCount + 1;
scanf("%s", &stringArray[i]);
printf("stringArray = %s when i = %d\t actualCount = %d\n", &stringArray[i], i, *actualCount);
}
printf("Finished!");
return stringArray;
}
With this code I am looping through a .txt file with some words inside. When I run this code, I see that I am indeed getting the correct words in the correct places in the array, but as soon as the loop reaches the end of the file the program gives me a segfault error. I'm guessing that this is because the loop is hitting the EOF value and throwing an error, but I can't figure out how to fix it. Here is a screenshot of the results: http://i.imgur.com/kduzBnp.png
Thanks for the help!
EDIT
I changed my code to this:
while(scanf("%s", &stringArray) != EOF) {
*actualCount = *actualCount + 1;
printf("stringArray = %s when actualCount = %d\n", &stringArray, *actualCount);
}
However, I'm still getting a segfault error with the same output values. So I know it's reading the file correctly, I just don't get why it stops at the end and throws an error.
You want to continue looping as long as scanf successfully reads a word from standard input.
So the termination condition for the loop should use the result returned by scanf.
scanf returns the number of items successfully read. It will return 1 if it successfully read a word, and either 0 or EOF otherwise.
But there are some other problems with your code.
char* stringArray = (char*)malloc(100*sizeof(char));
This doesn't allocate space for 100 strings, or even for 100 pointers to strings. It merely allocates space for a single array of 100 chars. And it's better written as:
char *stringArray = malloc(100);
Casting the result of malloc is unnecessary and can mask errors, and sizeof(char) is 1 by definition.
Your for loop reads successive words into memory starting at position 0 in the allocated array, then at position 1, then at position 2, etc, with each read overwriting part of the previous one.
Also, scanf with a "%s" format is inherently unsafe, since it will read as many characters as the user types (or from whatever stdin is connected to), regardless of the size of the target array.
It's safer to use fgets() to read lines of text, and then perhaps sscanf to parse the input (though sscanf has some of its own problems).
And if you want to store multiple strings, you'll need to allocate space for them. I'm not certain enough about what you're trying to do to offer more specific advice.
scanf() is generally a poor function to use, but, as gleaned from the comments, if you insist on using it, the following code does what I presume you want to do, here:
#include <stdio.h>
#include <stdlib.h>
char ** create_string_array(const size_t num_strings, const size_t maxlen) {
char ** new_array = malloc(num_strings * sizeof(*new_array));
if ( new_array == NULL ) {
perror("Couldn't allocate memory for string array.");
exit(EXIT_FAILURE);
}
for ( size_t i = 0; i < num_strings; ++i ) {
new_array[i] = malloc(maxlen);
if ( new_array[i] == NULL ) {
perror("Couldn't allocate memory for string.");
exit(EXIT_FAILURE);
}
}
return new_array;
}
void free_string_array(char ** array, const size_t num_strings) {
for ( size_t i = 0; i < num_strings; ++i ) {
free(array[i]);
}
free(array);
}
char ** readScores(int* actualCount) {
char ** stringArray = create_string_array(14, 100);
for (int i = 0; i < 14; ++i) {
int status = scanf("%s", stringArray[i]);
if ( status == 0 || status == EOF ) {
break;
}
*actualCount = *actualCount + 1;
printf("stringArray = %s when i = %d\t actualCount = %d\n",
stringArray[i], i, *actualCount);
}
printf("Finished!\n");
return stringArray;
}
int main(void) {
int num_strings = 0;
char ** stringArray = readScores(&num_strings);
printf("There were %d strings read. They are:\n", num_strings);
for ( int i = 0; i < num_strings; ++i ) {
printf("%2d: %s\n", i + 1, stringArray[i]);
}
free_string_array(stringArray, num_strings);
return EXIT_SUCCESS;
}
and with a suitable datafile outputs:
paul#local:~/src/c/scratch$ cat data_file
Twas
brillig
and
the
slithy
toves
did
gyre
and
gimble
in
the
wabe
paul#local:~/src/c/scratch$ cat data_file | ./strcount
stringArray = Twas when i = 0 actualCount = 1
stringArray = brillig when i = 1 actualCount = 2
stringArray = and when i = 2 actualCount = 3
stringArray = the when i = 3 actualCount = 4
stringArray = slithy when i = 4 actualCount = 5
stringArray = toves when i = 5 actualCount = 6
stringArray = did when i = 6 actualCount = 7
stringArray = gyre when i = 7 actualCount = 8
stringArray = and when i = 8 actualCount = 9
stringArray = gimble when i = 9 actualCount = 10
stringArray = in when i = 10 actualCount = 11
stringArray = the when i = 11 actualCount = 12
stringArray = wabe when i = 12 actualCount = 13
Finished!
There were 13 strings read. They are:
1: Twas
2: brillig
3: and
4: the
5: slithy
6: toves
7: did
8: gyre
9: and
10: gimble
11: in
12: the
13: wabe
paul#local:~/src/c/scratch$
Keith already pointed out the fundamental errors you had, namely, if you need a dynamic array of strings, then you need to malloc() memory for an array of pointers to char *, and then for each one, malloc() memory for the string itself, which your original code does not do, and you need to be checking the return from scanf() for 0 and EOF.
You could replace your for loop with a while loop.
while (fgets(buffer, buffer_size, fp)) {
// do something with buffer
}
if (ferror(fp)) {
// handle the error, usually exit or return
} else {
// continue execution
}
char* readScores(int* actualCount) {
char* stringArray = (char*)malloc(100*sizeof(char));
int i=0, len;
while(scanf("%s%n%*c", &stringArray[i], &len)==1){
printf("stringArray = %s when i = %d\t actualCount = %d\n", &stringArray[i], i, ++*actualCount);
i += len + 1;
}
printf("Finished!");
return stringArray;
}
The code you have offered has no issue. Neither myself, nor my MSVC on Windows got any troubles in working with it. Here's how it looks like:
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int main( )
{
FILE * asd;
char* stringArray = calloc( 100, sizeof(char) );
int actualCount = 0;
freopen_s( &asd, "wsx.txt", "w+", stdin );
fprintf_s( stdin, "this is a test this is only a test this also is a test" );
rewind( stdin );
for ( int i = 0; i <= 13; i++ ) {
actualCount = actualCount + 1;
scanf_s( "%s", &stringArray[i], 100 - i );
printf_s( "stringArray = %s when i = %d\t actualCount = %d\n", &stringArray[i], i, actualCount );
}
printf( "Finished!" );
Sleep( 5000 );
return 0;
}
And the output is as you'd expect it to be, with no errors... So my answer is that the problem you are experiencing is due to something other than the code you've written.

How to get numbers from this type of string in C

1 13 3 4; 5 6 7 8; 9 10 11 12; 2 15 14 0
How can I get numbers from this string in ANSI C?
I tried to separate it with strtok() :
char *vstup = argv[1];
char delims[] = ";";
char *result = NULL;
result = strtok( vstup, delims );
while( result != NULL ) {
printf( "result is \"%s\"\n", result );
result = strtok( NULL, delims );
}
and I got this:
result is "1 13 3 4"
result is " 5 6 7 8"
result is " 9 10 11 12"
result is " 2 15 14 0"
Now I don't know how to get numbers in integers and save them to two-dimensional field (matrix). I need something like this:
field[1][1] = 1
.
.
.
etc.
I'm wondering about atoi(), but I'm not sure, if it would recognize for example "13" as one number..
Use even space as delimiter. For example in ur case this code put the numbers in 2d array of size 4x4
#include<stdio.h>
#include<string.h>
void main()
{
char a[] = "1 13 3 4; 5 6 7 8; 9 10 11 12; 2 15 14 0";
int i=0 ,j=0 , x;
int array[4][4];
char *temp;
temp = strtok(a," ;");
do
{
array[i][j] = atoi(temp);
if(j == 4)
{
i++;
j = 0;
}
j++;
}while(temp = strtok(NULL," ;"));
for(i=0; i<4; i++)
{
for(j=0; j<4 ;j++)
{
printf("%d ",array[i][j]);
}
printf("\n");
}
}
You can do the exact same thing you did for stripping up to the ';' but instead also use ' ' for spaces. Place this result into an array and you can use atoi or whatever you want on the entire array. If you want to put it into a 2-d array you can split the string up to the ';' and then within that loop split each integer into whatever part of the array you want to. Won't write the code as it looks like homework.
One way is to use sscanf:
char* input = ...;
while(*input) {
input += ';' == *input;
int a, b, c, d, n = -1;
sscanf(input, "%d %d %d %d%n", &a, &b, &c, &d, &n);
if(n < 0)
// parsing error
// parsed successfully into a, b, c, d
input += n;
}
Note, that the input string is left unchanged here.

Resources