Click here to Skip to main content
15,892,005 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Giving an array with size of N the C program will read a text file that contain numbers separeted by whitespace and will store them into the array. The N number is the first one in the file and is in different line than the other numbers.

Example of txt file:

C
10
9 8 5 4 585 2 14 5 9 8 


I want to make a check the exact time the array will save the number, if there are more numbers than the actual size of the array (eg 12 numbers) to exit.

I search all the web to find a solution but I couldn't.

I created a code that read the file with fscanf, but it slow down the program if should read more than 200.000 elements.

Here's the code anyway :

C
File *stream
stream = fopen("xxx_big.txt", "r");
	
	
	int t_size;
	
	 fscanf(stream, "%d", &t_size);
	int num = 0;           											
				int value = 0;    												

				while ( fscanf ( stream, "%d", &value) == 1)
				{ 																                                                        
				num++; 				                                                   
				}                     
				if ( num > t_size) 	
									
				{                     
				printf ( "too many integers\n");	
				getchar();			
				return 1;			
				}                     
				if ( num < t_size) 	
									
				{                     
				printf ( "not enough integers\n");	
				getchar();			
				return 1;			
				}      
	
			fclose(stream);


My program use getline() to read and split the numbers into a char and then using the following code will save the numbers into the array:

C
count = atoi(lines[0]); // First row has count 
	my_array = (int*)malloc(count * sizeof(int));
	if (my_array==NULL) {
		printf("Error allocating memory!\n"); //print an error message
		return 1; //return with failure
		getchar();
		}
	for (i = 0; i < count; ++i) {
		my_array[i] = atoi(lines[i + 1]);
	}


But as I mentioned I already put the numbers into a char so that check should be easy enough to create.

Here's all the code (without the fscanf check):

C
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int is_end(char* input) {
	return *input == 0;
}
 
int is_linebreak(char* input) {
	return *input == '\r' || *input == '\n' || *input == ' ';
}
 
char* eat_linebreaks(char* input) {
	while (is_linebreak(input))
		++input;
 
	return input;
}
 
size_t count_lines(char* input) {
	char* p = input;
	size_t rows = 1;
 
	if (is_end(p))
		return 0;
	
	while (!is_end(p)) {
		if (is_linebreak(p)) {
			++rows;
			p = eat_linebreaks(p);
		}
		else {
			++p;
		}
	}
	return rows;
}
 
/* split string by lines */
char** get_lines(char* input, size_t line_count) {
	char* p = input;
	char* from = input;
	size_t length = 0;
	size_t line = 0;
        int i;
	char** lines = (char**)malloc(line_count * sizeof(char*));
 
	do {
		if (is_end(p) || is_linebreak(p)) {
			lines[line] = (char*)malloc(length + 1);
			for (i = 0; i < length; ++i)
				lines[line][i] = *(from + i);
 
			lines[line][length] = 0;
			length = 0;
			++line;
			p = eat_linebreaks(p);
			from = p;
			
		}
		else {
			++length;
			++p;
		}
	} while (!is_end(p));
 
	// Copy the last line as well in case the input doesn't end in line-break
	lines[line] = (char*)malloc(length + 1);
	for (i = 0; i < length; ++i)
		lines[line][i] = *(from + i);
 
	lines[line][length] = 0;
	++line;
 

	return lines;
}
 
int main(int argc, char* argv[]) {

	char** lines;
	size_t size;
	size_t number_of_rows;
	int count;
	int* my_array;

 
	FILE *stream;
	char *contents;
	int fileSize = 0;
        int i;
 
	// Open file, find the size of it
	stream = fopen("xxx.txt", "r");
	
	
	if (stream == NULL) 
    {
        printf("Opening 'xxx.txt' file failed: %s\n",strerror(errno)); 
        getchar();               
        return 0;                
    } 
	else { 
	

	fseek(stream, 0L, SEEK_END);
	fileSize = ftell(stream);
	fseek(stream, 0L, SEEK_SET);
 
	// Allocate space for the entire file content
	contents = (char*)malloc(fileSize + 1);
 
	// Stream file into memory
	size = fread(contents, 1, fileSize, stream);
	contents[size] = 0; 
	fclose(stream);
 
	// Count rows in content
	number_of_rows = count_lines(contents);
 
	// Get array of char*, one for each line
	lines = get_lines(contents, number_of_rows);
	
	
	// Get the numbers out of the lines
	count = atoi(lines[0]); // First row has count
	my_array = (int*)malloc(count * sizeof(int));
	if (my_array==NULL) {
		printf("Error allocating memory!\n"); //print an error message
		return 1; //return with failure
		getchar();
		}
	for (i = 0; i < count; ++i) {
		my_array[i] = atoi(lines[i + 1]);
	}
	
	
	printf("All up and running! Array created! :D \n\n Array values: \n");
		for(i = 0; i < count; i++ )
		{
		printf(" %d : %d\n", i, my_array[i]);
		}
	
	
	free(my_array);
	fclose(stream);
	

	return 0;
	}
}
Posted
Updated 22-Nov-14 7:37am
v2

1 solution

This is the latest repeat of this question and does not seem to be going anywhere. It has been suggested more than once that you read the entire file into memory first and then you can process it much faster. Use one of the token splitting functions[^] to get the first number, and then all others in the list. This allows you to iterate over the numbers, once to count them, and then a second time to convert them to integers and save them in the array.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900