Here is my code so far
#define MAXROWS 60
#define MAXCOLS 60
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
main()
{
char TableFileName[100];
char PuzzleFileName[100];
char puzzle[MAXROWS][MAXCOLS];
char line[MAXCOLS];
FILE *TableFilePtr;
int cols;
int rows;
cols=0;
rows=0;
printf("Please enter the table file name: ");
scanf("%s",TableFileName);
/* ... */
TableFilePtr = fopen(TableFileName, "r");
//printf("\n how many rows and colums are there? separate by a space: ");
// scanf("%d %d",&rows, &cols);
while(fgets(line, sizeof line, TableFilePtr) != NULL)
{
for(cols=0; cols<(strlen(line)-1); ++cols)
{
puzzle[rows][cols] = line[cols];
}
/* I'd give myself enough room in the 2d array for a NULL char in
the last col of every row. You can check for it later to make sure
you're not going out of bounds. You could also
printf("%s\n", puzzle[row]); to print an entire row */
puzzle[rows][cols] = '\0';
++rows;
}
/*int c;
for(c=0; c<MAXROWS; ++c){
fgets(puzzle[rows], sizeof puzzle[rows], TableFilePtr);
}*/
printf("%s",puzzle[5][5]);
}
what i would like to do is make it so it reads from a text file which contains a wordsearch in a txt file so that it has just random letters. i would like to be able to make it so that i am able to say puzzle[5][5] and it gives me the character in the 4th row and 4th column. I am running into a segmentation fault and i do not know how to fix it though.
You are trying to print a string with printf("%s", puzzle[rows][cols]) and giving a char puzzle[rows][cols] is 1 character and not a string.
do this: printf("%c", puzzle[rows][cols]); instead.
char puzzle[MAXROWS][MAXCOLS];
char line[MAXCOLS];
//...
while(fgets(line, sizeof line, TableFilePtr) != NULL)
{
for(cols=0; cols<(strlen(line)-1); ++cols)
{
puzzle[rows][cols] = line[cols];
}
puzzle[rows][cols] = '\0';
++rows;
}
This is dangerous because you never check that the number of lines is less than MAXROWS or that the length of each line is less than MAXCOLS. That means that a malformed data file can cause you to write beyond the bounds of the puzzle array, which can cause a segmentation fault, corrupted memory, or other problems.
To fix, you need to include limits in the loop conditions, like this:
while (frets(line, sizeof line, TableFilePtr) != NULL && rows < MAXROWS) {
for (cols=0; cols<(strlen(line)-1) && cols < MAXCOLS; ++cols) {
//...
I didn't see obvious errors except you didn't check the boundary of puzzle array when you write chars into it. so I think maybe a possible reason is your input file is too large to fit into puzzle array then the array has been overflowed.
Related
I need to load the contents of a file into two string arrays. I tried the following and it is not working.
file.txt contains 10 records and each record has two string values separated by whitespace.
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char line[12][20];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
fptr = fopen("file.txt", "r");
char arr[20][20];
while (fgets(line, sizeof(line), fptr)) {
strcpy(arr[i],line);
i++;
}
tot=i;
for (int i=0; i<tot; i++) {
printf("first value %s",arr[i][0]);
printf("second value is %s",arr[i][1]);
printf("\n");
}
return 0;
}
If I understand correctly, you're trying to store data in a structure like:
{{"line1A", "line1B"}, {"line2A", "line2B"}, {"line3A", "line3B"}}
It looks like you need an array where each element consists of two arrays (strings), one for the first value and one for the second value on each line. If this is the case, you need a three dimensional array of chars.
In the example below I've declared arrayOfLines as array with 12 elements each of which has 2 arrays of chars (for your two values per line), with space for 20 chars in each string (NULL terminated char array)
There are some other problems with your code:
The first parameter for fgets() should be a char * - a pointer to a string buffer. Your code passes in a multi-dimensional array of chars.
Your while loop should continue until fgets returns NULL
You need to split each line into multiple strings
Check for buffer overruns when copying strings with strcpy()
In the example code I used strtok() delimited by a " " space character - you may need to play around with this - strtok can accept an array of chars to be used as a delimiter. In the example, I split the first string using the first space char, and the second string is delimited by the end of line.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
// Array for 12 lines, each with 2 strings, each string max 20 chars
// Adjust values as required.
char arrayOfLines[12][2][20];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
fptr = fopen("file.txt", "r");
// char arr[20][20]; not needed
char line[20];
while(fgets(line, sizeof(line) / sizeof(line[0]), fptr) != NULL)
{
// Rudimentary error checking - if the string has no newline
// there wasn't enough space in line
if (strchr(line, '\n') == NULL) {
printf("Line too long...");
return EXIT_FAILURE;
}
// Split string into tokens
// NB: Check for buffer overruns when copying strings
char *ptr1 = strtok(line, " ");
strcpy(arrayOfLines[i][0], ptr1);
char *ptr2 = strtok(NULL, "\n");
strcpy(arrayOfLines[i][1], ptr2);
i++;
}
tot=i; // Unecessary - just use a different variable in your loop and use i as the upper bound
for (int i=0;i<tot;i++)
{
printf("first value %s\n", arrayOfLines[i][0]);
printf("second value is %s\n", arrayOfLines[i][1]);
printf("\n");
}
return 0;
}
printf("first value %s",arr[i][0]);
printf("second value is %s",arr[i][1]);
Basicly all you are doing is printing 2 chars from i word when you want to print full string you should do it like this: printf("%s",arr[i]); You said that value is separated by whitespace so when you are getting line from file you will save it to arr[i] (if first line in file contains "Hello World", your arr[0] will contain "Hello World") when you want to split it into 2 printf you need to print them char by char until space.
Edit: I reminded myself about function sscanf you can use it to get data from file array like you whould do it with keyboard input
You can use this to do that
Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void){
char line[12][20];
char arr[20][20];
FILE *fptr=NULL;
int i=0;
fptr = fopen("file.txt", "r");
if(!fptr){
printf("cant open file\n");
exit(1);
}
while(fgets(*line, sizeof(line), fptr)){
strncpy(arr[i],*line, sizeof(*line));
i++;
}
for (int j=0;j<i;j++){
printf("%s\n", arr[j]);
}
return 0;
}
Notes and changes I made on your code:
Check fptr as return value of open() if it's NULL decide what to do.
Remove unnecessary tot variable and use another index j in last for loop.
Use strncpy() as a better version of strcpy()
Correct way of print arr, printf("%s\n", arr[j]);
\n can be embed on first printf()
I am taking in a variable amount of lines of string using fgets. The end of each line is marked by a new line. I am trying to allocate an array of strings (using malloc). Each index of the array will point to each line of the text that is entered from the user. This was really tough to explain so here is an example:
Using fgets and malloc, allow the user to enter multiple lines of strings. The user will signal the end of the strings with a '.' on a newline. Each line of the multiple strings will be stored as a string in a dynamically allocated array. The output of the program must print each line in reverse order.
Ex:
Enter string:
(this is sample input)
The sky is blue
The grass is green
I love life
.
(this should be the output)
I love life
The grass is green
The sky is blue
I have this so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char charsOnLine[1000];
char **poem;
int i;
int j;
fgets(charsOnLine, 1000, stdin); //runs only once
while (charsOnLine[0] != '.')
{
poem = malloc(sizeof(char*) * 3);
for(j = 0; j < strlen(charsOnLine); j++)
{
poem[j] = malloc(sizeof(strlen(charsOnLine)));
strcpy(poem[j], charsOnLine);
}
fgets(charsOnLine, 1000, stdin);
}
for (j = 0; j < strlen(*poem); j++) //test to print each line of the poem (not in reverse)
{
printf("%s\n",poem[j]);
}
return 0;
}
I am have just started with double pointers, pointers, dynamically allocating memory, fgets() and putting them all together is giving me some trouble.
In my code, I'm testing to see if it'll print each line I enter the same way I entered it, but it is printing the last entered string 4 times instead of each different line.
Once I figure out how to print each entered line, I will figure out how to print them backwards.
There's a rather simple solution to your "in reverse order" problem, which does not even require dynamic memory allocation but just recursion:
void readRecursive() {
char charsOnLine[1000];
if (fgets(charsOnLine, 1000, stdin) && charsOnLine[0] != '.') {
readRecursive();
}
fputs(charsOnLine, stdout);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char charsOnLine[1000];
char **poem = NULL;
size_t size = 0, current;
while (fgets(charsOnLine, 1000, stdin) != NULL && charsOnLine[0] != '.')
{
char **tmp;
tmp = realloc(poem, (size + 1) * sizeof(*poem));
if(tmp)
{
poem = tmp;
poem[size] = malloc(strlen(charsOnLine) + 1);
if(poem[size])
{
strcpy(poem[size++], charsOnLine);
}
}
}
current = size;
while(current--)
{
fputs(poem[current], stdout);
}
/* do something more with your read poem */
return 0;
}
I have a program that reads file A and then copies the contents to file B.
I would like to write to file B every third character. I created a loop that rewrites every third item to a new char array. In file B I get strange characters. What am I doing wrong?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
int i;
char full_string[100];
char reduce_string[100];
char file_name_for_read[128];
char file_name_for_save[128];
printf("Enter file name for read...\n");
scanf ("%s", file_name_for_read);
strcat(file_name_for_read,".txt");
FILE *fileA;
fileA=fopen(file_name_for_read,"r");
printf("Enter file name for save...\n");
scanf ("%s", file_name_for_save);
strcat(file_name_for_save,".txt");
FILE *fileB;
fileB=fopen(file_name_for_save,"w");
while(fgets(full_string, sizeof(full_string), fileA) !=NULL)
{
for(i = 2; i < 100; i+=3)
{
reduce_string[i-=2] = full_string[i+=1];
}
fprintf(fileB, "%s", reduce_string);
}
fclose(fileA);
fclose(fileB);
}
What am I doing wrong?
Several things. At minimum,
In your inner loop, you iterate over the full length of full_string, regardless of how many of those bytes were actually read from the file by the most recent fgets().
In your inner loop, you invoke undefined behavior because the expression reduce_string[i-=2] = full_string[i+=1] has two side effects on the value of i that are unsequenced relative to each other.
In that expression, i - 2 is anyway not the index you want except when i is 2, because you increment i by 3 at each iteration. You'll end up filling some positions and skipping others.
You do not add a null terminator at the end of the data copied into reduce_string.
Your strategy does not anyway result in copying every third character of the file; rather, it copies every third character of each line. These differ unless all the line lengths of the input files are multiples of 3.
reads file A and then copies the contents to file B. I would like to write to file B every third character.
If lines are not important,
seems simple to read 3 characters and write the 3rd one.
for(;;) {
fgetc(fileA);
fgetc(fileA);
int ch = fgetc(fileA);
if (ch == EOF) break;
fputc(ch, fileB);
}
or
int ch;
do {
fgetc(fileA);
fgetc(fileA);
ch = fgetc(fileA);
} while (ch != EOF && fputc(ch, fileB) != EOF);
The easiest way is to use a different index for each array, that way each can go at their own speed.
int i,x;
for(i = 0, x=0; i < 1000; i+=3, x++)
{
reduce_string[x] = full_string[i];
}
fprintf(fileB, "%s", reduce_string);
Check this code out. In your code, you have reduce_string[i-=2] = full_string[i+=1]; — I don't know where you come up with it, but this was not working.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ()
{
int i;
char full_string[100];
char reduce_string[100];
char file_name_for_read[128];
char file_name_for_save[128];
printf("Enter file name for read...\n");
scanf ("%s", file_name_for_read);
strcat(file_name_for_read,".txt");
FILE *fileA;
fileA=fopen(file_name_for_read,"r");
printf("Enter file name for save...\n");
scanf ("%s", file_name_for_save);
strcat(file_name_for_save,".txt");
FILE *fileB;
fileB=fopen(file_name_for_save,"w");
while(fgets(full_string, 50, fileA) !=NULL)
{
int cnt = 0;
for(i = 2; i < strlen(full_string)-3; i+=3)
{
reduce_string[cnt++] = full_string[i];
}
fprintf(fileB, "%s", reduce_string);
}
fclose(fileA);
fclose(fileB);
}
I have a text file with just random letters in rows and columns. All I would like to do is make a 2d array so that it's puzzle[i][j] where if I put printf("%c", puzzle[5][4]); it would simply give me the 4th row and 3rd columns character (since it starts at 0 in an array). Here is my code so far.
#define MAXROWS 60
#define MAXCOLS 60
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
main()
{
FILE *TableFilePtr;
char TableFileName[100];
char PuzzleFileName[100];
char puzzle[MAXROWS][MAXCOLS];
printf("Please enter the table file name: ");
scanf("%s",TableFileName);
TableFilePtr=fopen(TableFileName, "r");
if(TableFilePtr == NULL)
{
printf("Can't open %s", TableFileName);
exit(EXIT_FAILURE);
}
char words;
int n;
n=0;
int i,j,row,col;
int rowcount, colcount;
printf("\n how many rows and colums are there? separate by a space: ");
scanf("%d %d",&row, &col);
/* while(fscanf(TableFilePtr,"%c",&words)!= EOF)
{
printf("%c",words);
}
*/
/*for (colcount=0;colcount<col;colcount++)
{
for (rowcount=0;rowcount<row;rowcount++)
{
printf("%c ",words);
}
printf("\n");
}
*/
for(i=0;i<row;i++){
for(j=0;j<col;j++){
fscanf(TableFilePtr, "%c %s\n",&puzzle[i]][j]);
//puzzle[i][j]=words;
// printf("%c ", puzzle[i][j]);
}
printf("\n");
}
}
The commented area at the end (just the starting part) works to simply print out the text file in the compiler. I would like to get it to be in a 2d array though.
for(colcount=0;colcount<col;colcount++){...}
I would do something like this (I didn't use all of your exact variable names but you get the idea):
char puzzle[MAXROWS][MAXCOLS], line[MAXCOLS];
FILE *infile;
int cols = 0, rows=0;
/* ... */
infile = fopen(TableFileName, "r");
while(fgets(line, sizeof line, infile) != NULL)
{
for(cols=0; cols<(strlen(line)-1); ++cols)
{
puzzle[rows][cols] = line[cols];
}
/* I'd give myself enough room in the 2d array for a NULL char in
the last col of every row. You can check for it later to make sure
you're not going out of bounds. You could also
printf("%s\n", puzzle[row]); to print an entire row */
puzzle[rows][cols] = '\0';
++rows;
}
Edit: much shorter version will have newline and NULL chars at the end of each row unless you manually pick them off. You may have to tweak puzzle[][] (use MAXCOLS +/- n or some such) to make it work for you.
for(c=0; c<MAXROWS; ++c){
fgets(puzzle[rows], sizeof puzzle[rows], infile);
}
At the end of the loop, puzzle[x][y] should be a 2d array of chars from your input file. Hope that helps.
I was asked to:
Create an ANSI C program that will read a textfile containing a 25 x 25 matrix of the character ‘x’ or the blank space.
Display the initial generation using the function printf.
Calculate the next generation using the rules mentioned above and save it in another textfile.
The filenames of the input and output textfiles should be specified as command-line parameters.
all i have so far is a code that asks for the text file then my code prints it. i lack the codes applying the rules of Conway's Game of Life. I don't know where to put it. and what codes to use. :( please help me.
here`s what i have now:
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LEN 80
#define N 25
void display(char [][N+1], size_t);
int main(int argc, char *argv[]) {
FILE *fp;
char in[MAX_LINE_LEN];
char grid[N][N+1] = { { '\0' } };
size_t i = 0;
printf("Enter filename: ");
fgets(in, MAX_LINE_LEN, stdin);
*(strchr(in, '\n')) = '\0';
if ((fp = fopen(in, "r")) != NULL) {
while ((i < N) && (fgets(in, MAX_LINE_LEN, fp) != NULL)) {
*(strchr(in, '\n')) = '\0';
/* should verify only 'x' and space in string before storing */
strncpy(grid[i++], in, N);
}
/* pad each row with spaces, if necessary, for NxN array */
for (i = 0; i < N; i++) {
while (strlen(grid[i]) < N) {
strcat(grid[i], " ");
}
}
/* For all generations ...
compute next generation */
display(grid, N);
/* End for all generations */
} else {
printf("%s not found.\n", in);
getch();
}
getch();
}
void display(char a[][N+1], size_t n) {
size_t i;
for (i = 0; i < n; puts(a[i++]));
}
*(strchr(in, '\n')) = '\0';
Bad juju. If strchr returns NULL, this will segfault. I know your data will always have a newline, but it's a bad habit to get into. Always assign the result of strchr to a variable and perform a NULL check first:
char *tmp = strchr(in, '\n');
if (tmp)
*tmp = 0;
Frankly, I think treating your grid as an array of strings will cause more grief than it will solve. Treat it like you would a 2d array of any other type. Dealing with the newlines at the end of each line in the input file will be a pain no matter what you do.
As far as how to structure your code, think about the problem at a high level:
You need to load a file as your starting grid;
You need to calculate the grid for the next generation, for some number of generations;
You need to display each grid;
You need to write each grid to a file.
You've already split the display code out into its own function; you just need to do the same for the load, calculate, and write functions (you could leave the file loading code in main, but it would make the code cleaner if you put it in its own function).
void load(const char *filename, char (*grid)[N], size_t rows) {...}
void calc(char (*grid)[N], size_t rows) {...}
void save(const char *filename, char (*grid)[N], size_t rows) {...}
So each time through in main, you'll just call calc on the grid before calling display, then you'll call save to write the new grid to a file.
As for how to calculate the next grid, well, that's part of your assignment, and I don't want to give it all away.