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
Related
I'm trying to print line numbers in the beginning of the lines without using fgets()
yes, it prints line number well when I input multiple files
but I want to get result like this. Can you guys help me with this?
Now result
1 I'll always remember
2 the day we kiss my lips
3
4 light as a feather
*5 #####localhost ~ $*
expect result
1 I'll always remember
2 the day we kiss my lips
3
4 light as a feather
*#####localhost ~$*
Here is my code:
#include <stdio.h>
int main(int argc, char *argv[]) {
FILE *fp;
int c, n;
n = 1;
for (int i = 1; i < argc; i++) {
if (argc < 2)
fp = stdin;
else
fp = fopen(argv[i], "r");
c = getc(fp);
printf("%d ", n);
while (c != EOF) {
putc(c, stdout);
if (c == '\n')
n++, printf("%d ", n);
c = getc(fp);
}
fclose(fp);
}
return 0;
}
Do not write printf("%d ", n); when you do not know if there is the next line. Or, otherwise, do printf("%d ", n); only on the beginning of the file and after a newline when you know there is a next char.
#include <stdbool.h> // for bool, true, false
bool previous_character_was_a_newline = true;
while ((c = getc(fp)) != EOF) {
if (previous_character_was_a_newline) {
previous_character_was_a_newline = false;
printf("%d ", n);
}
putc(c, stdout);
if (c == '\n') {
n++;
previous_character_was_a_newline = true;
}
}
Do not write code like n++, printf("%d ", n);, it will be confusing. Strongly prefer:
if (c == '\n') {
n++;
printf("%d ", n);
}
Your implementation outputs the line number before the first line and after each newline, including the one at the end of the file. This causes an extra line number to appear at the end of the file.
Let's define the output more precisely:
you want the line number at the beginning of each line, no output if no line, no line number after the last line.
do you want the line counter to reset to 1 when a new file is read? I assume no, but cat -n does.
do you want to output an extra newline at the end of a non empty file that does not end with a newline? I assume yes but cat -n does not.
Here is a modified version where the answer is no for the first question and yes for the second:
#include <stdio.h>
int output_file(FILE *fp, int line) {
int c, last = '\n';
while ((c = getc(fp)) != EOF) {
if (last == '\n') {
printf("%d\t", line++);
}
putchar(c);
last = c;
}
/* output newline at end of file if non empty and no trailing newline */
if (last != '\n') {
putchar('\n');
}
return line;
}
int main(int argc, char *argv[]) {
int n = 1;
if (argc < 2) {
n = output_file(stdin, n);
} else {
for (int i = 1; i < argc; i++) {
FILE *fp = fopen(argv[i], "r");
if (fp == NULL) {
perror(argv[i]);
} else {
n = output_file(fp, n);
fclose(fp);
}
}
}
return 0;
}
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 wrote a short code that should copy the content of a file into an initialized array of strings and then print that array. I get no errors/warnings but still the program doesn't print anything when i run it. The code is the following:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int dim = 30;
int main() {
char* arr[dim];
int i = 0;
FILE* fp;
fp = fopen("test.txt", "r+");
if(fp == NULL) {
printf("\nError, breaking...");
return 0;
}
while(i <= dim) {
arr[i] = (char *)malloc(dim*sizeof(char *));
++i;
}
i = 0;
while(fscanf(fp, "%s", arr[i]) != EOF) {
printf("%s: added\n", arr[i]);
++i;
}
}
The file contains a series of words separated only by whitespaces and newline characters.
correct followings and see if it helps
1) initialise i to 0 ie. i=0;
2)
while(i < dim) { } // it should be < as array start with 0
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.
I am using isalpha() to determine if there are characters on the line and it is showing that the line "90 1 0" contains alphabetic characters.
Here is the relevant code
bool digitTest(char *test, int arysize)
{
int i;
for (i =0; i<arysize; i++)
{
if ((isalpha(test[i])) != 0){
return 0;
}
if (i==arysize)
return 1;
i++;
}
return 1;
}
It is called here
char buffer[4096] = {};
while(NULL!=fgets(buffer, sizeof(buffer), fp)){
if (digitTest(buffer, 4096) == 0){
printf ("contains alpha\n");
continue;
/*printing code if there is no alphabetic characters below, i do not believe it is relevant*/
and this is output
1
1
1
contains alpha
contains alpha
contains alpha
25123.90
54321.23
6
and input
1
1
1
89 23.5 not a number
90 1 0
-5.25 not a number 10000
25123.90 54321.23 6
The code has a few problems:
You shouldn't check all buffer. Check buffer until \0. because the output of fgets is a C-style string.
Second problem is an extra i++ in function digitTest. You should remove it.
You don't need arysize any more.
Use this digitTest function instead
int digitTest(char *test)
{
int i;
for (i=0; test[i] && test[i] != '\n'; i++)
{
if (isalpha(test[i]) != 0)
return 0;
}
return 1;
}
(maybe has minor bugs, I didn't test it)
And call it like this:
while( fgets(buffer, sizeof(buffer), fp) ) {
if (!digitTest(buffer)) {
printf ("contains alpha\n");
continue;
}
}
It Looks like you might be accessing locations in memory that contain characters, Change your code to
char buffer[4096] = {};
memset(buffer, 0, 4096);
while(NULL!=fgets(buffer, sizeof(buffer), fp)){
if (digitTest(buffer, strlen(buffer)) == 0){ //get actual length of buffer
printf ("contains alpha\n");
continue;
EDIT
In order to make your code not respond to either \n or \r do
bool digitTest(char *test, int arysize)
{
int i;
for (i =0; i<arysize; i++)
{
if( test[i] == '\r' || test[i] == '\n')
return 1;
if ((isalpha(test[i])) != 0){
return 0;
}
if (i==arysize)
return 1;
}
return 1;
}