I'm trying to make a program that translates words that are in a file and puts them in another file. Here I'm trying to read the words and put them into an array so I can search for them later and then print back into another file the translated word.
For the moment I'm trying to read and print from the array:
#include<stdio.h>
#include <string.h>
int main()
{
char rom_eng[4][2], fran_eng[4][2];
int i, j;
FILE* re = fopen("rom_eng.txt", "r");
FILE* out = fopen("out.txt", "w");
if (re == NULL)
{
printf("Error");
return 1;
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 4; j++)
fscanf(re, "%s", &rom_eng);
}
for (i = 0; i < 2; i++)
{
for (j = 0; j < 4; j++)
fprintf(out, "%s \n", rom_eng);
}
return 0;
}
The words in the file are like this:
- word word
- word word
The output is the same last word repeatedly printed in the out file.
You define : char rom_eng[4][2], fran_eng[4][2];
And then you read: fscanf(re, "%s", &rom_eng);
You 're not supposed to put the '&' before rom_eng because it is defined as a char, and chars are already pointers to adresses, so in this case you dont need to put the '&' to point to the adress.
Related
I am quite new to C programming and I have been set the task of reading a .csv file containing a 2d integer array, I need to then print it so it shows up in the terminal. The array is a 4 row by 2 col integer array, but when I use this code I get a random list of numbers. I have attached the code I used and the .csv file array and how it should look like.
#include <stdlib.h>
#include <stdio.h>
int main()
{
FILE *in_data = fopen("in.csv", "r");
int i;
int j;
int trIn[4][2];
if(in_data == NULL)
{
printf("error\n");
return 1;
}
for(i = 0; i < 4; i++){
for(j = 0; j < 2; j++){
char junk;
if (j != 0) fgetc(in_data);
fscanf(in_data, "%c%d%c", &junk, &trIn[i][j], &junk);
printf("%d ", trIn[i][j]);
}
fgetc(in_data);
printf("\n");
}
return 0;
}
.csv file array:
0 0
0 1
1 0
1 1
.csv file (raw):
"0","0"
"0","1"
"1","0"
"1","1"
You can create a pattern which discards the unwanted characters, like so:
Live demo
for (i = 0; i < 4; i++)
{
for (j = 0; j < 2; j++)
{
//printf("%s", str); //print str to check if there are any weird chars
fscanf(in_data, " \"%d\",", &trIn[i][j]);
printf("%d ", trIn[i][j]);
}
printf("\n");
}
Chek if you have spaces in the lines after the values, that can throw fscanf off. Although a space before the specifier, like in the sample, should solve that.
Also, you can export .csv files without the quotation marks, if that's something you can control.
You can also try a more robust method using a combo of fgets and sscanf:
Live demo
char str[20];
int i = 0;
int j = 0;
//...
while (i < 4 && fgets(str, sizeof str, in_data))
{
//printf("%s", str); //print str to check if there are any weird chars
if(sscanf(str, "\"%d\",\"%d\"", &trIn[i][j], &trIn[i][j+1]) == 2)
printf("%d %d\n", trIn[i][j], trIn[i][j+1]);
i++;
}
You can replace you current loop with this one:
for(i = 0; i < 4; i++){
for(j = 0; j < 2; j++){
char junk;
if (j != 0) fgetc(in_data);
fscanf(in_data, "%c%d%c", &junk, &trIn[i][j], &junk);
printf("%d ", trIn[i][j]);
}
fgetc(in_data);
printf("\n");
}
This works because fscanf(in_data, "%d", &trIn[i][j]) reads an int (%d) from the file in_data into the memory location of trIn[i][j]. fgetc didn't work because it only reads a single character which was then printed as if it were an integer.
EDIT: Now, for each value in the .csv file, you read to a junk variable the " and \n characters.
Line by line:
if (j != 0) fgetc(in_data); reads the , from the csv file into a junk variable (which isn't the first character on a line).
fscanf(in_data, "%c%d%c", &junk, &trIn[i][j], &junk); reads:
1st: the opening " character into a junk variable
2nd: the number (int: %d) into to memory location of trIn[i][j].
3rd: the closing " character into a junk variable
I'm having trouble inputting strings from a file into my 2D char array (string array). I need to do it with pointers, however, it produces a weird jumble of the last and second to last words. Also, I cannot use the string library functions.
Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fin, *fout;
char lineRead[20], arr2[20][20];
int i, j, k, len;
fin = fopen("cp4in_1.txt","r");
if (fin){
while(fscanf(fin,"%s",&lineRead) != EOF){
char *pointer = lineRead;
for (k = 0; lineRead[k] != '\0'; k++);
for (i = 0; i < 4; i++){
for (j = 0; j < k; j++){
arr2[i][j] = *pointer;
pointer++;
}
}
}
}
else{
printf("Couldn't find file.\n");
}
}
Here is cp4in_1.txt:
ABCDE
PQRSTFG
acegikmoqsuwyz
bdfhjlnprtvx
The result I'm looking for should have arr2 contain an array of strings saying "ABCDE", "PQRSTFG", "acegikmoqsuwyz", and "bdfhjlnprtvx".
The main problem was that you were looping through arr[i] inside the while loop
And do not forget to place '\0' at the end of each string. Also, you were declaring char pointer several times inside the while loop, it is the error as well.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fpin, *fpout;
char lineRead[20], arr2[20][20], *pointer;
int i = 0, j, k, len;
fpin = fopen("cp4in_1.txt","r");
if (fpin){
while(fscanf(fpin,"%s", lineRead) != EOF){
pointer = lineRead;
for (k = 0; lineRead[k] != '\0'; k++);
for(j = 0; j < k; j++){
arr2[i][j] = *pointer;
pointer++;
}
arr2[i][j+1] = '\0';//place zero char at the end of the string
i++;
if(i >= 4)
break;
}
}
else{
printf("Couldn't find file.\n");
}
//output the result
for(i = 0; i < 4; i++){
printf("%s\n", arr2[i]);
}
return 0;
}
Output:
ABCDE
PQRSTFG
acegikmoqsuwyz
bdfhjlnprtvx
you should always terminate your string with \0 so:
for (i = 0; i < 4; i++){
for (j = 0; j < k; j++){
arr2[i][j] = *pointer;
pointer++;
}
arr2[i][j]='\0';
}
also your program need a little change
int main()
{
FILE* p;
p = fopen("file.txt", "r+");
int i = 0, j, k;
char* pointer, lineRead[20], arr2[20][20];
if (p != NULL)
{
while (!feof(p))
{
fscanf(p, "%s", &lineRead);
for (k = 0; lineRead[k] != '\0'; k++);
pointer = lineRead;
for (j = 0; j < k; j++)
{
arr2[i][j] = *pointer;
pointer++;
}
arr2[i][j] = '\0';
i++;
}
for (int i = 0; i < 4; i++)
{
printf("%s\n", arr2[i]);
}
}
else
{
printf("Couldn't find file.\n");
}
return 0;
}
The biggest issue you are facing is trying to do line-oriented input with a formatted-input function. (and you are using it wrong) Using fscanf (the scanf family of functions) is full of pitfalls for the new C programmer. Until you know what they are, avoid using them and instead use the line-oriented input functions fgets() or POSIX getline() which ensure an entire line of input is consumed each time.
In your case, the array lineRead decays to a pointer on access, C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3), so your use of &lineRead is wrong (resulting in parameter for fscanf() having type char ** instead of the correct char*). No '&' is required because lineRead is already a pointer, thus the correct use would be:
while(fscanf(fin,"%19s",lineRead) == 1){
(note: you must also provide the field-width modifier to limit the read of characters to what will fit in lineRead -- including the nul-terminating character. Otherwise you use of fscanf() is no more secure than using gets() -- which has been removed from C11 completely)
That is just one of the many pitfalls waiting to bite you using the scanf family.
Instead, using a line-oriented input function, you can do:
#include <stdio.h>
#define ROWS 20
#define COLS ROWS /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
char arr[ROWS][COLS];
size_t n = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
/* while array not full, read line into array */
while (n < ROWS && fgets (arr[n], COLS, fp)) {
char *p = arr[n]; /* pointer to start of string */
do { /* loop until '\n' found */
if (*p == '\n')
*p = 0; /* overwrite with nul-terminating char */
} while (*p && *++p);
n++; /* increment line counter */
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (size_t i = 0; i < n; i++) /* output stored lines */
printf ("line %2zu : %s\n", i, arr[i]);
}
Using a line-oriented input function, the '\n' is read from input and included in the buffer filled. Your only job is to remove the trailing '\n' from the buffer. This is normally done with, e.g. arr[n][strcspn(arr[n], "\n")] = 0;, but since you cannot use string.h a simple loop will work just fine.
Example Use/Output
With your input file in dat/cp4int_1.txt, you would pass the filename to the program as it's first argument and receive the following output:
$ ./bin/readcp4int_1 dat/cp4int_1.txt
line 0 : ABCDE
line 1 : PQRSTFG
line 2 : acegikmoqsuwyz
line 3 : bdfhjlnprtvx
Look things over and let me know if you have further questions.
I currently have a program where I read in a .txt file like so: ./myprogram < input.txt and put each character in my array. This code looks something like this:
char myArray[SIZE_ROW][SIZE_COL];
for (int i = 0; i < SIZE_ROW; i++) {
for (int j = 0; j < SIZE_COL; j++) {
fscanf(stdin, "%c ", &myArray[i][j]);
}
}
Before I fill myArray I would like to make sure that input.txt has the format of SIZE_ROW characters by SIZE_COL characters, for for example if SIZE_ROW and SIZE_COL were both equal to 4, so a valid input.txt could look something like this:
.p..
k...
..q.
.P..
while an invalid input.txt could look like this:
.....q.
..k..p
p..
While I'm checking the format, I would also like to make sure that input.txt only contains the characters q, k and p for example.
I have tried using fgets() to read in the file line by line, but when I do this, using scanf afterwards to fill myArray seems to not work. I also do not know the name of the file beforehand, so the only way I can open it is as shown above: ./myprogram < input.txt.
Some pseudo code to get you started.
int Read_EsoFile(char myArray[RSIZE][CSIZE], FILE *istream) {
for each row (0 to RSIZE -1)
char buf[CSIZE+3];
read line using fgets and detect EOF
truncate potential trailing \n
test if valid
length == CSIZE?
elmenet only `q k p`?
save in myArray[i]
return success status
}
// example usage
char myArray[RSIZE][CSIZE];
int result = Read_EsoFile(myArray, stdin);
I also do not know the name of the file beforehand, so the only way I can open it is as shown above: ./myprogram < input.txt.
If you do not know the name of the file beforehand, the only way to open it is not: ./myprogram < input.txt. You can use command line arguments to open the file using its name which is passed as a command line argument at runtime, like: ./myprogram input.txt.
Here is the code to do that, plus I have also applied all the checks that you asked for and then applied your code to get the data into the array and printed the array in the end to verify the contents:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define SIZE_ROW 4
#define SIZE_COL 4
int main(int argc, char* argv[])
{
if(argc == 2)
{
FILE *f = fopen(argv[1], "r");
char* buffer = NULL;
size_t n = SIZE_COL;
int rows = 0, cols;
int flag = 1;
int i, j;
while(!feof(f))
{
getline(&buffer, &n, f);
if(strlen(buffer) > 1) // to skip blank lines
{
cols = strlen(buffer)-1;
if(cols != SIZE_COL)
{
break;
}
for(i=0; i<cols; i++)
{
if(!(buffer[i] == '.' || buffer[i] == 'q' || buffer[i] == 'Q' || buffer[i] == 'k' || buffer[i] == 'K' || buffer[i] == 'p' || buffer[i] == 'P'))
{
break;
}
}
if(i<cols)
{
flag = 0;
break;
}
rows++;
free(buffer);
buffer = NULL;
}
}
if(flag)
{
if(cols == SIZE_COL)
{
if(rows == SIZE_ROW)
{
rewind(f);
char myArray[SIZE_ROW][SIZE_COL];
for (i = 0; i < SIZE_ROW; i++)
{
for (j = 0; j < SIZE_COL; j++)
{
fscanf(f, "%c ", &myArray[i][j]);
}
}
for (i = 0; i < SIZE_ROW; i++)
{
for (j = 0; j < SIZE_COL; j++)
{
printf("%c ", myArray[i][j]);
}
printf("\n");
}
}
else
{
printf("Row size is not %d.\n", SIZE_ROW);
}
}
else
{
printf("Column size is %d not %d.\n", cols, SIZE_COL);
}
}
else
{
printf("Invalid characters in file.\n");
}
fclose(f);
}
else
{
printf("Invalid Arguments! Please give file name as argument from command line.\n");
}
return 0;
}
Ask me, if you do not understand anything in the code. You should call it like:
./myprogram input.txt
I am reading from a file of which each line is longer than 63 characters and I want the characters to be truncated at 63. However, it fails to truncate the lines read from the file.
In this program we are assuming that the file has 10 lines only:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char a[10][63];
char line[255];
int count = 0;
//Open file
FILE *fp;
fp = fopen("lines.dat", "r");
//Read each line from file to the "line array"
while(fgets(line, 255,fp) != NULL)
{
line[63] = '\0';
//copy the lines into "a array" char by char
int x;
for(x = 0; x < 64; ++x)
{
a[count][x] = line[x];
}
count++;
}
fclose(fp);
//Print all lines that have been copied to the "a array"
int i;
for(i = 0; i < 10; i++)
{
printf("%s", a[i]);
}
}
You have this result because you forgot to add the null string terminator in the end of a[0].
There's several ways to do it. My favorite one is to leave line as is: since it seems you want the truncated string elsewhere, you souldn't modify the source.
In that case, you can replace:
//Tries to truncate "line" to 20 characters
line[20] = '\0';
//copying line to each character at a time
int x;
for(x = 0; x < 20; x++)
{
a[0][x] = line[x];
}
with
//copying line to each character at a time
int x;
for(x = 0; x < 20; x++)
{
a[0][x] = line[x];
}
a[0][20] = 0;
i think you are missing the null byte.
You can get more info about this at : Null byte and arrays in C
I am coding a program which takes a text file as an input, makes the index of the words of it and prints the output(the index) in a file and in the screen. I coded as below and tried much to spot the problem or at least narrow it down, but I couldn't. If anyone can help or spots a problem in syntax or the logic of the code, I would be happy to know.
void main(int argc, char * argv[])
{
//clearscreen
clrscr();
//if arguments are less that default of the program
if (argc < 2)
{
cout << "You should've input 3 arguments." ;
return;
}
//opening the input file and defining a pointer which points to it as argv[1]
FILE *fPtr = fopen(argv[1], "r+");
//defining a 2D array to hold maximum to 200 words holding maximum to 20 characters
char words[200][20];
//initializing words 2D array with zero ASCII
for(int i = 0; i < 200; i++)
for(int j = 0; j < 20; j++)
words[i][j] = 255;
//defining an 2D whi array which is supposed to show how many times words are placed in which lines in a defined layout
//it holds maximum to 200 words holding maximum 100 sentences
int index[200][100];
//initializing the index 2D array with zero ASCII
for(i = 0; i < 200; i++)
for(j = 0; j < 100; j++)
index[i][j] = 0;
//this array of characters max to 2000 is supposed to hold each line which is gotten with fgets
char buff[2000];
//initializing the buff array with zero ASCII
for(i = 0; i < 2000; i++)
buff[i] = 0;
//the max of the words used in the source file is 200. but this valuable named as 'last' says how many words are used in this source file
//its initalized as no words is held
int last = 0;
//defining a pointer to char of punctuation mark characters. all ASCII codes expect for a - z, A - Z, 0 - 9 and newline
char *punc;
//initializing punctuation marks array
for(i = 0; i < 256; i++)
{
if(i == 10)
continue;
if(i >= '0' && i <= '9')
continue;
if(i >= 'a' && i <= 'z')
continue;
if(i >= 'A' && i <= 'Z')
continue;
char *string = (char *) &i;
strncat(punc, string, 1);
}
//how many lines is read from the source file
int lineread = 0;
//a word which the processes are done on that
char *word;
//one line read
while( fgets(buff, 1999, fPtr) != NULL)
{
//how many words is read from the source file in the current line
int wordread = 0;
word = strtok(buff, punc);
//one word read
while( word != NULL)
{
//sorting
int k = 0;
while(strcmp(word, words[k])> 0)
k++;
if(strcmp(word, words[k]))
{
for(int l = last; l >= 0; l--)
{
strcpy(words[l + 1],words[l]);
for(int o = 0; o <= lineread; o++)
index[l + 1][o] = index[l][o];
}
last++;
strcpy(words[k],word);
for(l = 0; l <= lineread; l++)
index[k][l] = 0;
}
index[k][lineread]++;
wordread++;//go to next word
word = strtok(NULL, punc);
}
lineread++;//go to next line
}
//closing the input file
fclose(fPtr);
//opening the output file and defining a pointer which points to it as argv[2]
FILE *fPtr2 = fopen(argv[2], "w+");
//showing the index in cmd
for(i = 0; i <= last; i++)
{
printf("%-20s" , words[i]);
fprinf(fPtr2, "%-20s" , words[i]);
int m = 0;
for(j = 0; j <= lineread; j++)
{
if(m)
{
printf("%c", ',');
fprintf(fPtr2, "%c", ',');
}
if(index[i][j])
{
printf("%i", j + 1);
fprintf(fPtr2, "%i" ,j + 1);
}
if(index[i][j] > 1)
{
printf("(%i)", index[i][j]);
fprintf(fPtr2, "(%i)", index[i][j]);
m = 1;
}
}
printf("\n");
fprintf(fPtr2, "\n");
}
//closing the output file
fclose(fPtr);
}
now it errors as Abnormal program termination NULL pointer assignment. I have to use turbo c and I use DOS SHELL. there's a file names as "input.txt" in resourse. and in DOS SHELL I write this:
programname.exe input.txt output.txt
and my desired output if input.txt is this:
hello. hello.
how are
you? hello.
desired output:
hello 1(2),3 //2 times in line 2, 1 time in line 1
how 2 //1 time in line 2
are 2 //1 time in line 2
you 3 //1 time in line 3
the problem is with this line:
while(strcmp(word, words[k])> 0)
Because index is initialized as 255 and according to the algorithm strcmp works based on, for first word the code works right and puts it in word[0] but for the second word it won't work properly.for example:
first word: Kittens
second word: Biscuits
first strcmp compares Kittens with 255 ASCII code. the result is that Kitten is smaller and the process will put it in word[0]. But for the second word, strcmp compares Biscuits with Kittens and the result is that Kittens is bigger and program will go through another blocks of word[] which in not wanted. the program will be fixed by initializing word[] to 0 and using this code instead of that which is first mentioned:
while(strcmp(word, words[k])> 0)