txtfile.txt is a file with 30 lines, each line having 50 characters.
I need to copy each character from txtfile into into Carray. How can I do this? I get a segmentation fault when I try.
I have tried the most obvious approach, which is just copying c into the array.
int cArray[29][49];
fp = fopen("input_blinker.txt", "r");
if(fp==NULL){
perror("Error in opening file");
return(-1);
}
int columnInd = 0;
int rowInd = 0;
do {
c = fgetc(fp);
if (feof(fp)) {
break;
}
cArray[rowInd][columnInd] = c;
columnInd++;
if (columnInd > 29){
rowInd++;
columnInd=0;
}
} while(1);
fclose(fp);
return(0);
I expect the value of c will be copied into the given index of cArray, but I know that isn't correct. Once again, I am getting segmentation fault. Thanks for any help (still learning c)
Your array isn't big enough:
int cArray[29][49];
This creates a 2D array of size 29 x 49. You need an array of 30 x 50:
int cArray[30][50];
Your bounds checks are also incorrect:
cArray[rowInd][columnInd] = c;
columnInd++;
if (columnInd > 29){
rowInd++;
columnInd=0;
}
The size of the second dimension is 49, 50 after fixing it, so you should be checking that value. You should also put in a check to make sure your row index doesn't exceed the bounds of the array.
if (columnInd >= 50){
rowInd++;
columnInd=0;
}
if (rowInd >= 30) {
break;
}
Related
I need to read a file of ints into an array in C. A sample of the file I need to read is below, though note the files this will process can have thousands or hundreds of thousands of lines.
127
234
97
8723
I've gotten the file open in C, read how many lines there are so I know how many spaces my array needs, but I can't seem to read/parse each line into the array.
FILE *file;
int N = 0;
char filePath[30];
char endFile;
printf("What file should be used?\n");
scanf("%s", filePath);
file = fopen(filePath, "r");
if(file == NULL) {
printf("This file failed to open.\n");
break;
}
for(endFile = getc(file); endFile!=EOF; endFile=getc(file))
if(endFile == '\n') {
N = N+1;
}
int myArray[N];
while(fscanf(file, "%d\n", &a) != EOF) {
fscanf(file, "%d\n", &a); // I'm not sure this line is needed...
printf("%d\n", a);
M[i] = a;
}
From here, I need to read the file contents into myArray, with each line being the corresponding spot in the array (i.e. line zero is myArray[0], line one is myArray[1], etc.). I can't seem to find a way to do this, though I see several methods to do tab-delimited 2d arrays or csv multi-dimensional arrays.
Please also let me know if creating the array/determining the array size can be done in a better way than literally counting new-line characters...
There's no need to first "count the number of lines".
The following code cautiously grows an array of integers (by increments of 10).
#define GROW 10
int *rec = NULL, nRec = 0, sz = 0;
while( fgets( buf, sizeof buf, ifp ) != NULL ) {
if( nRec == sz ) {
rec = realloc( rec, (nRec+GROW) * sizeof *rec );
/*omitting test for failure */
sz += GROW;
}
rec[ nRec++ ] = atoi( buf );
}
This shows what is possible.
Note that realloc() can fail, returning NULL... It's up to you to add a bit of code to handle that condition.
Further, some conventional thought is to double the size of the allocation when needed (because realloc() may not be 'cheap'.) You can decide if you want to grow the array in increments (of 1024?) or grow it exponentially.
Okay! Pretty new to this stuff!
This is part of a bit bigger task and the problem I have now is that I have a list of names (100 names) inside a text file. They're written like this:
Sam (enter) Oliver (enter) Paul (enter) --- and so on.
So every name is on its own row. I'm trying to read this into a char array which I'll then print out to check if it works. I'll have to do something else to it afterward but I want to figure that out later.
Here's my code right now: (File names etc. are in Finnish so don't bother with that! :D)
#include <stdio.h>
int main() {
FILE *tiedosto;
char *array[100];
char nimi[] = "names.txt";
tiedosto = fopen(nimi, "r");
if (tiedosto == NULL) {
printf("Tiedostoa ei voida avata");
return;
}
int i;
for (i = 0; i < 100; i++) {
fscanf(tiedosto, "%s", &array[i]);
}
fclose(tiedosto);
printf("Tulostetaan taulukko \n");
// printf("%s \n",array);
for (i = 0; i < 100; i++) {
printf("%s \n", array[i]);
}
return 0;
}
You have got several errors in the code:
In this line:
fscanf(tiedosto, "%s", &array[i]);
You don't need to use an ampersand sign here. It's because the array is already the type of char*[] – in such situations, you must avoid passing char**.
In the following code segment:
if (tiedosto == NULL) {
printf("Tiedostoa ei voida avata");
return; // ***
}
The return type of the main() is an integer, so it must pass something non-void. Any non-zero return code would indicate an unsuccessful program closure.
In this declaration:
char *array[100];
The array is using a pointer alongside the array too. Thus this must be initialized using the malloc() function properly so that you don't hit with a segfault.
In case you don't want to get messed up of allocating memory, etc. try switching to two-dimensional array declaration:
char array[TOTAL_ENTRIES][PER_NAME_LEN];
I have described the 2-D array approach to avoid code complexity (read comments for explanation):
#include <stdio.h>
// Some global macros throughout this program
#define MAX_USERS 100
#define MAX_STRLEN 64
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
int main(void) {
const char *file_name = "names.txt";
FILE *fp = fopen(file_name, "r");
char name_list[MAX_USERS][MAX_STRLEN];
int count = 0;
// Using perror() is the best option here
if (fp == NULL) {
perror(file_name);
return EXIT_FAILURE;
}
// Reading the file contents and saving that into 2-D array
while (fscanf(fp, "%s", name_list[count++]) != EOF)
;
// Displaying the saved array contents
for (int i = 0; i < count - 1; i++)
fprintf(stdout, "%s\n", name_list[i]);
return 0;
}
In this program, the number of lines in the names.txt file can be anything lesser than or equal to 100.
Hi,
I need to count the usage of alphabetical characters in some plain text file. This is what i have came with. Basically just run through the text file and compare each character with the ASCII value of specific searched character.
When I run it, all I can see is just the first printf() string and just error of terminated status when I close the console.
I do have a text.txt file in same folder as the .exe file but I can't see anything.
Not sure if just my syntax is bad or even semantics.
Thx for help! :-)
#include <stdio.h>
#include <stdlib.h>
#define ASCIIstart 65
#define ASCIIend 90
void main(){
FILE *fopen(), *fp;
int c;
unsigned int sum;
fp = fopen("text.txt","r");
printf("Characters found in text: \n");
for (int i = ASCIIstart; i <= ASCIIend; i++){
sum = 0;
c = toupper(getc(fp));
while (c != EOF){
if (c == i){
sum = sum++;
}
c = toupper(getc(fp));
}
if (sum > 0){
printf("%c: %u\n",i,sum);
}
}
fclose(fp);
}
Instead of looking up the entire file for each character, you could do
FILE *fp;
int c, sum[ASCIIend - ASCIIstart + 1]={0};
fp = fopen("file.txt,"r");
if(fp==NULL)
{
perror("Error");
return 1;
}
int i;
while( (c = toupper(getc(fp)))!= EOF)
{
if(c>=ASCIIstart && c<=ASCIIend)
{
sum[c-ASCIIstart]++;
}
}
for(i=ASCIIstart; i<=ASCIIend; ++i)
{
printf("\n%c: %d", i, sum[i-ASCIIstart]);
}
You must check the return value of fopen() to ensure that the file was successfully opened.
There's an array sum which holds the the number of occurrences of each character within the range denoted with ASCIIend and ASCIIstart macros.
The size of the array is just the number of characters whose number of occurrences is to be counted.
sum[c-ASCIIstart] is used because the difference between the ASCII value (if the encoding is indeed ASCII) of c and ASCIIstart would give the index associated with c.
I don't know what you meant with FILE *fopen(), fp; but fopen() is the name of a function in C used to open files.
And by
FILE *fopen(), *fp;
you gave a prototype of a function fopen().
But in stdio.h, there's already a prototype for fopen() like
FILE *fopen(const char *path, const char *mode);
yet no errors (if so) were shown because fopen() means that the function can have any number of arguments. Have a look here.
Had the return type of your FILE *fopen(); were not FILE * or if it were shown to other parameter types like int, you would definitely have got an error.
And, void main() is not considered good practice. Use int main() instead. Look here.
You can use a character array and parse the file contents with one time traversal and display the array count finally.
#include <stdio.h>
#include<ctype.h>
void main(){
FILE *fopen(), *fp;
int c;
fp = fopen("test.txt","r");
printf("Characters found in text: \n");
char charArr[26]= {0};
c = toupper(fgetc(fp));
while(c!=EOF) {
charArr[c-'A']=charArr[c-'A']+1;
c = toupper(fgetc(fp));
}
fclose(fp);
for(int i=0;i<26;i++){
printf("\nChar: %c | Count= %d ",i+65,charArr[i]);
}
}
Hope this helps!!
because after first time you are end of the file.
and your c = toupper(getc(fp)); returning -1 after that.
For counting just one character, you are reading the whole file and repeating this for each and every character. Instead, you can do:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ASCIIstart 65
#define ASCIIend 90
int main(){
FILE *fp;
int c, i;
int alphabets[26] = {0};
fp = fopen("text.txt","r");
if (fp == NULL){
fprintf (stderr, "Failed to open file\n");
return -1;
}
while ((c = toupper(fgetc(fp))) != EOF){
if (c >= ASCIIstart && c <= ASCIIend)
alphabets[c - ASCIIstart]++;
}
fclose(fp);
fprintf(stdout, "Characters found in text: \n");
for (i = 0; i < 26; i++)
fprintf (stdout, "%c: %d\n", i+ASCIIstart, alphabets[i]);
return 0;
}
TLDR
Working with your code, your loops are inside-out.
I'll answer in pseudo-code to keep the concepts straightforward.
Right now you are doing this:
FOR LETTER = 'A' TO 'Z':
WHILE FILE HAS CHARACTERS
GET NEXT CHARACTER
IF CHARACTER == LETTER
ADD TO COUNT FOR CHAR
END IF
END WHILE
END FOR
The problem is you are running through the file with character 'A' and then reaching the end of file so nothing gets done for 'B'...'Z'
If you swapped this:
WHILE FILE HAS CHARACTERS
GET NEXT CHARACTER
FOR LETTER = 'A' TO 'Z'
IF LETTER = UCASE(CHARACTER)
ADD TO COUNT FOR LETTER
END IF
END FOR
END WHILE
Obviously doing 26 checks for each letter is too much so perhaps a better approach.
LET COUNTS = ARRAY(26)
WHILE FILE HAS CHARACTERS
CHARACTER := UCASE(CHARACTER)
IF CHARACTER >= 'A' AND CHARACTER <= 'Z'
LET INDEX = CHARACTER - 'A'
COUNTS[INDEX]++
ENDIF
END WHILE
You can translate the pseudo code to C as an exercise.
Rewind the pointer to the beginning of the file at the end of your for loop?
This has been posted before: Resetting pointer to the start of file
P.S. - maybe use an array for your output values : int charactercount[pow(2,sizeof(char))] so that you don't have to parse the file repeatedly?
edit: was missing pow()
SO i can have a input file that can have either a space or a new line between each number within the file. An example of this could be:
input.txt
2 3 4
4 3 2 3
2 3 1
5 4 3 2
2 5 4 2
How would i parse through the file and grab all of the elements and place them inside an array. Currently I have the following code:
#include<stdio.h>
#define FILE_READ "input.txt"
int main()
{
FILE * filp;
int count = 1;
char c;
filp = fopen(FILE_READ, "r");
if(filp == NULL)
printf("file not found\n");
while((c = fgetc(filp)) != EOF) {
if(c == ' ')
count++;
}
printf("numbers = %d\n", count);
return 0;
}
int myarray[count-1];
So how exactly would i push the numbers into the array at this point? I got the number of numbers in the file and created an array the size of the numbers. Now how exactly would i put the numbers into the array now?
This is a very simple thing to do, just use fscanf() to count how many values and then use malloc() to allocate space for them. Then, use fscanf() again to read the values into the array.
This might seem like a lot of work, but allocating space for every value is more. One optimization that can be worth the effort would be to allocate an estimate size array and then grow the array in multiples of the initial estimate using realloc() when you run out of space. This way, you reduce the number of allocations and at the same time you only loop through the values (reading from the file which is also expensive only once).
This is the easiest way I think
#include <stdlib.h>
#include <stdio.h>
int
main(void)
{
FILE *file;
int count;
int value;
file = fopen("input.txt", "r");
if (file == NULL)
return -1; // Error opening the file
count = 0;
while (fscanf(file, "%d", &value) == 1)
count += 1;
if (count > 0) {
int *array;
rewind(file);
array = malloc(count * sizeof(*array));
if (array == NULL) {
fclose(file);
return -1;
}
count = 0;
while (fscanf(file, "%d", &array[count]) == 1) {
fprintf(stdout, "%d\n", array[count]);
count += 1;
}
// Use the array now and then
free(array);
}
fclose(file);
return 0;
}
The code is supposed to read a user-inputted text file name, copy every character into a multidimensional array, then display it with standard output. It compiles, but produces unintelligible text. Am I missing something?
for (i = 0; i < BIGGEST; i++) {
for (j = 0; j < BIGGESTL; j++) {
if (fgetc(array, fp) ) != EOF)
array[i][j] = c;
else array[i][j] = '\0'
}
fclose(fp);
return 0;
}
You stop filling the array when you encounter EOF, but you print the full array out no matter what.
If the data read from the file is smaller than the input array, you will read that data in and then print that data out, plus whatever random characters were in the memory locations that you do not overwrite with data from the file.
Since the requirement seems to be to print text data, you could insert a special marker in the array (e.g. '\0') to indicate the position where you encountered EOF, and stop displaying data when you reach that marker.
You had better read each line from file
For example:
int i = 0;
while(fgets(text[i],1000,fp))
{
i++;
}
Though the question is edited and only part of the code is left in question. I am posting more than what is required for the question at the moment.
Reason being, there can be numberous improvements to originally posted full code.
In main() function:
You need to check for the argc value to be equal to 2 for your purpose and only then read in value of argv[1] . Else if program executed without the command-line-argument which is file_name in this case, invalid memory read occurs, resulting in segmentation fault if you read in argv[1].
In read_file_and_show_the contents() function:
Stop reading file if end of file is reached or maximum characters is read and store in the character array.
Below Program will help you visualize:
#include <stdio.h>
/*Max number of characters to be read/write from file*/
#define MAX_CHAR_FOR_FILE_OPERATION 1000000
int read_and_show_the_file(char *filename)
{
FILE *fp;
char text[MAX_CHAR_FOR_FILE_OPERATION];
int i;
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("File Pointer is invalid\n");
return -1;
}
//Ensure array write starts from beginning
i = 0;
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while( (fgets(&text[i++],sizeof(char)+1,fp) != NULL) && (i<MAX_CHAR_FOR_FILE_OPERATION) ) ;
//Ensure array read starts from beginning
i = 0;
while((text[i] != '\0') && (i<MAX_CHAR_FOR_FILE_OPERATION) )
{
printf("%c",text[i++]);
}
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Execute the program along with file name to be read and printed. \n\
\rFormat : \"%s <file-name>\"\n",argv[0]);
return -1;
}
char *filename = argv[1];
if( (read_and_show_the_file(filename)) == 0)
{
printf("File Read and Print to stdout is successful\n");
}
return 0;
}