Reading file word by word - c

I don't know why but my code prints a list of (null)(null)(null)....
I have to print the list of words from a file 'words.txt'.
Another question is: fscanf ignore white spaces?
#define WORD_LENGTH 1024
#define SIZE_QUOTE 100
int main(){
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
long i;
for(i = 0; i < SIZE_QUOTE; i++){
if(!(malloc(sizeof(char) * (size_t)WORD_LENGTH)))
exit(1);
}
i = 0;
FILE *pf = fopen("words.txt", "r");
while(!feof(pf) && i < SIZE_QUOTE){
fscanf(pf, "%s", quote[i]);
printf("%s", quote[i]);
i++;
}
fclose(pf);
free(quote);
}

You're never assigning the return value of malloc() to quote[i] so they end up staying NULL (if you're lucky):
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
long i;
for(i = 0; i < SIZE_QUOTE; i++){
if(!(malloc(sizeof(char) * WORD_LENGTH)))
It should be something like this instead:
char **quote = malloc(sizeof(char*) * (size_t)SIZE_QUOTE);
for(int i = 0; i < SIZE_QUOTE; i++){
quote[i] = malloc(sizeof(char) * WORD_LENGTH);
if(!quote[i])
Also you could avoid malloc() entirely and statically initialize that array if all the sizes are known:
char quote[SIZE_QUOTE][WORD_LENGTH] = {{'\0'}};
Also, you should be free()-ing the individual quote[i] at the end too:
for(int i = 0; i < SIZE_QUOTE; ++i) free(quote[i]);
free(quote);
There's other mistakes that have been pointed out through the comments already, so I won't elaborate further.

Related

C dynamically growing array realloc issue

I want to implement dynamically growing array in C.
I read the words from a file to a char** array and when the array is full grow its size by 2. But when I reallocate the memory, the first two elements of the array is lost. I tried with lines = realloc() but it's crashing. What am I doing wrong?
test.txt:
test1
test2
test3
test4
test5
test6
test7
test8
test9 (no end of line)
my output:
─
đ%
test3
test4
test5
test6
test7
test9
Code:
#include <stdio.h>
#include <malloc.h>
int size = 8;
char **read(FILE *input, char **lines, int *lSize) {
for (int i = 0; !feof(input); i++) {
*lSize += 1;
if (*lSize > size) {
realloc(lines, (size *= 2) * sizeof(char *));
for (int j = (*lSize) - 1; j < size; j++) {
lines[j] = (char *) malloc(1024 * sizeof(char));
}
}
fscanf(input, "%s", lines[i]);
}
return lines;
}
int main(){
FILE *file = fopen("test.txt", "r");
if (file == NULL) {
return -1;
}
char **lines = malloc(size * sizeof(char *));
for (int i = 0; i < size; ++i) {
lines[i] = malloc(1024 * sizeof(char));
}
int lsize = 0;
read(file, lines, &lsize);
printf("lSize:%d\n", lsize);
printf("size:%d\n", size);
for (int i = 0; i < lsize; ++i) {
printf("%s\n", lines[i]);
}
for (int i = 0; i < size; ++i) {
free(lines[i]);
}
free(lines);
return 0;
}
given char **read(FILE *input, char **lines, int *lSize)
what does: realloc(lines, (size *= 2) * sizeof(char *)) do?
Well it changes the sizes of the memory block pointed to by lines, possibly by moving it.
That is why it returns a new pointer. Just assigning that new pointer back to lines won't help much (on its own) as that only updates the local variable lines in this function.
But luckily lines is also returned from the function. But its return value is ignored in main so after read returns, the lines in main may be a bogus pointer.
do lines = read(file, lines, &lsize) in main as well.

Limit in dynamic 2D array in C

The program creates a 2D array with malloc and func fills it. fprintf writes in a file. That's all folks.
But I am getting unexpected program exit form the program if I use big integers for height and width.
(30,60): OK
(60,80): not OK
(60,65): OK
(17,41): OK
(200,200): not OK
Does anybody have a clue?
int main() {
unsigned char **buf = (unsigned char **)malloc(height * sizeof(unsigned char*));
for (int i = 0; i < height; ++i)
buf[i] = (unsigned char *)malloc(width * sizeof(unsigned char));
func(buf);
FILE * f = fopen("foo.txt", "w+");
for(int i= 0;i<height;++i)
fprintf(f, "%s%c", buf[i], '\n');
fclose(f);
for (int i = 0; i < height; ++i)
free(buf[i]);
free(buf);
}
void func(unsigned char** buf) {
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j)
buf[i][j] = 48 + (i/10)%10;
buf[i][width] = '\0';
}
}
You need to allocate space for '\0'
buf[i] = (unsigned char *)malloc(image_width * sizeof(unsigned char));
buf[i][width] = '\0';
buf[i][width] does not exist
Try
buf[i] = malloc(image_width + 1);
This line writes outside the array.
buf[i][width] = '\0';
You need to allocate one more character.
buf[i] = (unsigned char *)malloc((width + 1) * sizeof(unsigned char));
And make sure to use height and width everywhere.

Error freeing char ***

This is the code:
I do know what is the problem, I tried for hours to fix it, but was not successful
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void input(char ***array1,int * sizeWords,int size)
{
for (int i = 0; i < size; i++)
{
char word[81] = "";
char descrip[201] = "";
int numAgdarot = 0;
//how mach agdarot
printf("how mach of agdarrot you want? ");
scanf("%d", &numAgdarot);
//save the count of agdarot
sizeWords[i] = numAgdarot;
do
{
printf("enter word number %d: ", i);
_flushall();
gets(word);
} while (textSpace(word) == False);
(array1)[i] = (char**)malloc(numAgdarot + 1 * sizeof(char*)); //set the num and agdarot
//save the word
(array1)[i][0] = (char*)malloc(strlen(word) * sizeof(char));
strcpy(array1[i][0], word);
//save the agdarot
for (int j = 1; j <= numAgdarot; j++)
{
printf("enter descrip number %d: ", i);
_flushall();
gets(descrip);
(array1)[i][j] = (char*)malloc(strlen(descrip) * sizeof(char));
strcpy(array1[i][j], descrip);
}
}
}
int main() {
int *sizeWords = NULL;
int size = 0;
char *x=NULL;// = "jk";
char *** array1 = NULL;
printf("enter number of word: ");
scanf("%d", &size);
array1 = (char***)malloc(size * sizeof(char**));
sizeWords = (int*)malloc(size * sizeof(int));
//x = temp(x,sizeWords);
//input the word and agdarot
input(array1, sizeWords, size);
for (int i = 0; i < size; i++)
{
for (int j = 0; j < sizeWords[i] + 1; j++)
{
free(array1[i][j]);
}
free(array1);
}
return 0;
}
I get a "HEAP CORRUPTION DELETED" error after Normal block. Why?
If i used a debugger I see the char * but i can not do a free..
Doing
malloc(strlen(word) * sizeof(char));
is almost always wrong. Remember that strings also contains an extra character that is not reported by the strlen function, the terminator character '\0'. That means your next call to strcpy will write beyond the end of the allocated memory.
What you should do is allocate memory for that extra terminator character as well:
array1[i][0] = malloc(strlen(word) + 1);
[Note that I changed the code, first because the parentheses around array are not needed, secondly because you in C one should not cast the return of malloc, and third because sizeof(char) is specified to always be 1.]
Remember to change on all other places where you use strlen in a call to malloc.
These allocations are too small:
(array1)[i][0] = (char*)malloc(strlen(word) * sizeof(char));
strcpy(array1[i][0], word);
// ...
(array1)[i][j] = (char*)malloc(strlen(descrip) * sizeof(char));
strcpy(array1[i][j], descrip);
You need an extra character for the terminating \0. strcpy() is writing into unallocated space.
Save yourself some trouble and:
(array1)[i][0] = strdup(word);
// ...
(array1)[i][j] = strdup(descrip);
And, as pointed out in the comments,
for (int i = 0; i < size; i++)
{
for (int j = 0; j < sizeWords[i] + 1; j++)
{
free(array1[i][j]);
}
free(array1);
}
should become:
for (int i = 0; i < size; i++)
{
for (int j = 0; j < sizeWords[i] + 1; j++)
{
free(array1[i][j]);
}
free(array1[i]);
}
free(array1);

C++ equivalent for C

Program for work with arrays in dynamic memory.
Need equivalent for C. Can anybody help?
const int n = 6;
char **words = (char**) malloc(n *sizeof(char*));
for(int i = 0 ; i < n; i++)
words[i] = (char*)malloc( 50 * sizeof(int));
for(int i = 0; i < n; i++)
{
cin>>words[i];
}
cout<<endl;
for(int i = 0; i < n; i++)
{
if(words[i][0] == 'q')
cout<<words[i]<<endl;
}
The only C++ parts there are cin and cout; you can change them easily:
cin>>words[i];
becomes
scanf("%s", words[i]);
or
gets(words[i]);
while
cout<<words[i]<<endl;
becomes
puts(words[i]);
By the way, in the cin/scanf/gets you have a potential buffer overflow, since you are allocating space for 6 characters but you are accepting input of any length. You should do instead:
scanf("%6s", words[i]);
or (more maintainable, since it uses n directly)
fgets(words[i], n, stdin);
(although this will include the trailing \n in the string)
The only C++ features you are using are cin and cout. replace cin>>words[i] with gets(words[i]) and cout<<words[i]<<endl with puts(words[i]).
Use scanf("%s", &words[i]) to input data from stdin and printf("%s\n", words[i]) to output to stdout.
As you wish:
const int n = 6;
char **words = (char**) malloc(n *sizeof(char*));
int i = 0;
for( i= 0 ; i < n; i++)
{
words[i] = (char*)malloc( 50 * sizeof(char));
}
for(i = 0; i < n; i++)
{
scanf("%s", words[i]);
}
printf("\n");
for(i = 0; i < n; i++)
{
if(words[i][0] == 'q')
printf("%s\n", words[i]);
}

Getting every other line empty on output

I have a problem with getting every other line empty on output with this code. The desired output is: http://paste.ubuntu.com/1354365/
While I get: http://paste.ubuntu.com/1356669/
Does anyone have an idea of why I'm getting these empty lines on every other line?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *fp;
FILE *fw;
int main(int argc, char *argv[]){
char buffer[100];
char *fileName = malloc(10*sizeof(char));
char **output = calloc(10, sizeof(char*));
char **outputBuffer = calloc(10, sizeof(char*));
fw = fopen("calvin.txt", "w+");
for(int y = 0; y < 6; y++){
for(int i = 0; i < 10; i ++)
{
output[i] = malloc(100);
}
for(int x = 0; x < 12; x++){
sprintf(fileName,"part_%02d-%02d", x, y);
fp = fopen(fileName, "rb");
if(fp == NULL)
{
printf("Kan ikke åpne den filen(finnes ikke/rettigheter)\n");
}
else if(fp != NULL){
memset(buffer, 0, 100);
for(int i = 0; i < 10; i++){
outputBuffer[i] = malloc(100);
}
fread(buffer, 1, 100, fp);
for(int i = 0; i < 100; i++){
if(buffer[i] == '\0')
{
buffer[i] = ' ';
}
else if(buffer[i] == '\n')
{
buffer[i] = ' ';
}
}
for(int i = 0; i < 10; i++) {
strncpy(outputBuffer[i], buffer + i * 10, 10);
strncat(output[i], outputBuffer[i]+1, 11);
}
}
}
for(int i = 0; i < 10; i++){
printf("%s\n", output[i]);
}
}
fclose(fp);
free(fileName);
}
You are not reading correcting from the file. On the first image in the beginning you have:
o ""oo " o o o
on the second
""oo o o o
That does not make a lot of sense because it is the first line. It is not related to empty lines since we are talking about the first line.
It seems that you are reading -2 characters from the left so " prints over o the other " on the ' ' ect..
Try this away, may not be the most efficient solution:
int read(char *file)
{
FILE *fp = NULL;
int size = 0, pos = 0,i;
fp = fopen(file,"r");
if (!fp) return 0;
for(; ((getc(fp))!=EOF); size++); // Count the number of elements in the file
fclose(fp);
char buffer[size];
fp = fopen(file,"r");
if (!fp) return 0;
while((buffer[pos++]=getc(fp))!=EOF); // Saving the chars into the buffer
for(i = 0; i < pos; i++) // print them.
printf("%c",buffer[i]);
fclose(fp);
return 1;
}
This part seems problematic:
strncpy(outputBuffer[i], buffer + i * 10, 10);
strncat(output[i], outputBuffer[i]+1, 11);
1) Why is it necessary to use the extra outputBuffer step?
2) You know that strncpy() isn't guaranteed to null-terminate the string it copies.
3) More significantly, output[i] hasn't been initialized, so strncat() will concatenate the string after whatever junk is already in there. If you use calloc() instead of malloc() when creating each output[i], that might help. It's even possible that your output[i] variables are what hold your extra newline.
4) Even if initialized to an empty string, you could easily overflow output[i], since you're looping 12 times and writing up to 11 characters to it. 11 * 12 + 1 for the null terminator = 133 bytes written to a 100-byte array.
In general, unless this is a class assignment that requires use of malloc(), I don't understand why you aren't just declaring your variables once, at the start of the program and zeroing them out at the start of each loop:
char fileName[10];
char output[10][100];
char outputBuffer[10][100];
And, as stated by others, your allocating a bunch of memory and not trying to free it up. Allocate it once outside of your loop or just skip the allocation step and declare them directly.

Resources