C: issue with printing 2d array - c

I'm working on my C code, and got a problem with printing my 2d array. Instead of printing one string at the time, it prints the entire array from the asked point.
As an example, the input is, "Dog", "Cat", "Hat". Then it would print out:
DogCatHat
CatHat
Hat
This is what my code is suppsoed to do: It reads from a file. It creates an array of char arrays. Where each char array has 30 chars in them, read from file one char at the time. Then it prints out one char array per line.
This is what the code looks like:
char fname[] = "folder/text.txt";
char arry[30][30];
FILE *file;
file = fopen(fname, "r");
for(int x=0; x<30; x++){
for(int i=0; i<30; i++){
arry[x][i] = fgetc(file);
}
}
fclose(file);
for(int i=0; i<30; i++){
printf("%s\n", arry[i]);
}
Most likely I have just made an obvious mistake, but I'm not able to find it. So please help.

I think strings in file are not null terminated. So you need to put null character at the last character of the array.
char arry[30][30]
for(int x=0; x<30; x++){
for(int i=0; i<29; i++){ //You can write 29 characters + '\0'
arry[x][i] = fgetc(file);
}
arry[x][29] = '\0';
}
for(int i=0; i<30; i++){
printf("%s\n", arry[i]);
}

Related

C reading a file of binary numbers drops first char

Can anyone help me understand why the first char read from the file is dropped when I increase the file size to be > 19 rows?
When I run this with < 20 rows it works perfect, reads the input and dumps it. when I add a 20th row the first row of input drops the leading char when I print the array.
Im lost. :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
int i, j = 0;
FILE *pFile;
char string[20][12];
char file_contents_resultset[20][12];
pFile = fopen("sonar.txt", "r");
if (pFile == NULL)
{
printf ("error opening file");
return 0;
}
// Load 20 row of input into in an array and store a copy
for (i = 0; i < 20; i++)
{
fscanf (pFile, "%12s", &string[i]);
strcpy (file_contents_resultset[i], string[i]);
}
//Dump the first 5 rows of the array
printf ("Dump array contents \n");
for (i = 0; i < 5; i++)
{
for (j = 0; j < 12; j++)
{
printf ("%c", file_contents_resultset[i][j]);
}
printf ("\n");
}
fclose (pFile);
return 0;
};
This is my input file.
000110010001
101000110000
000110010111
100011100010
111001100001
001010001010
010100100101
011000010000
111111011010
001111011101
011011010010
001100010101
001010101100
000000000000
100010111111
100100110011
111100100001
011110001110
000110100101
011101111001
and this is the output
Dump array contents
00110010001
101000110000
000110010111
100011100010
111001100001
and this is the output if I delete the 20th row of input in the input file. Note the first char is no longer dropped.
Dump array contents
000110010001
101000110000
000110010111
100011100010
111001100001
Your one of the arrays you use for reading is redundant. You can use only string[][] or only file_contents_resultset[][].
I found that your problem is in the strcpy() call. Reading from the buffer is fine, but strcpy() seems to copy a blank character in the memory location of file_contents_resultset[0][0].
So to fix it by keeping as much of the program intact i did:
// ...
// stores only one row at a time
char string[12];
// ...
for (int i = 0; i < 20; i++) {
fscanf(pFile, "%12s", &string);
strcpy(file_contents_resultset[i], string);
}
// ...
}
If you want to be more concise and save memory, you can remove string altogether and just write:
// ...
// char string[12];
char file_contents_resultset[20][12];
// ...
// brackets in loops and other blocks can be omitted
// if the block is just 1 line long.
for (int i = 0; i < 20; i++)
fscanf(pFile, "%12s", &file_contents_resultset[20][12]);
// ...

Adding and Printing elements of an array in C

This is a function that is trying to perform the first step of converting a CFG to Chromsky Normal From by adding 0->S as a rule to the end of the list of rules. My rules are an array of characters. For some reason it will only print the array the first time and not any time after that. I want it to print the input and then result once the array has been edited. I cannot figure out why it won't print. The output is just the original input and then blank spaces.
UPDATE: It will now print both times, but the output of the second print is the same as the first. It is not registering that I added ',','0','>','S' as elements to the array. Am I adding the elements wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//global variables
char stringCFG[200];
//a program to convert CFG to Chromsky Normal Form
int main(int argc, char *argv[]){
//intialize instance variables
FILE *CFG;
FILE *output;
char ch;
int RHS= 0;
int isThereS= 0;
int howManyItems= 0;
CFG= fopen(argv[1], "r");
output= fopen(argv[2], "w");
for (int i=0; i<200; i++){
fscanf(CFG, "%c", &stringCFG[i]);
howManyItems++;
fprintf(output,"%c", stringCFG[i]);
}
printf("\n");
for(int i=0; i<200; i++){
if(stringCFG[i] == '>'){
RHS= 1;
}
if(stringCFG[i] == ','){
RHS= 0;
}
if(RHS== 1){
if(stringCFG[i] == 'S'){
isThereS=1;
}
}
}
if(isThereS==1){
stringCFG[howManyItems]= ',';
howManyItems++;
stringCFG[howManyItems]='0';
howManyItems++;
stringCFG[howManyItems]='>';
howManyItems++;
stringCFG[howManyItems]='S';
howManyItems++;
}
for(int i=0; i<200; i++){
fprintf(output,"%c",stringCFG[i]);
}
fclose(CFG);
fclose(output);
}
The problem seems to be here:
for (int i=0; i<200; i++){
fscanf(CFG, "%c", &stringCFG[i]);
howManyItems++;
fprintf(output,"%c", stringCFG[i]);
}
This loop always executes 200 times regardless of what is in the file. In other words - the value of howManyItems will be 200 when the loop is done.
You can check that simply by printing howManyItems after the loop, i.e.
printf("After loop, howManyItems=%d\n", howManyItems);
Since you have:
char stringCFG[200];
then
stringCFG[howManyItems]= ','; // bad.. writing to stringCFG[200]
howManyItems++;
stringCFG[howManyItems]= '0'; // bad.. writing to stringCFG[201]
howManyItems++;
...
will write outside of the array. That is undefined behavior.
You need to stop the first loop once the whole file has been read. Something like:
for (int i=0; i<200; i++){
if (fscanf(CFG, "%c", &stringCFG[i]) != 1)
{
// No more data
break;
}
howManyItems++;
fprintf(output,"%c", stringCFG[i]);
}
and all the following loops must then use howManyItems as the upper limit.
Like
for(int i=0; i<howManyItems; i++){
if(stringCFG[i] == '>'){
RHS= 1;
}
...
}
BTW: Since you want to be able to add 4 extra chars, you probably should do:
char stringCFG[200]; --> char stringCFG[200 + 4];
BTW: Hard-coding the value 200 over and over again is bad practice. Instead use a define like:
#define MAX_CHARS 200
and replace all the hard-coded 200 with MAX_CHARS. Then you can adjust the maximum simply by editing one line instead of multiple lines.

C program prints garbage characters

I have an assignment to write a program in C that functions similarly to the bash sed 's/oldstring/newstring/g' but only using stdio.h and string.h. We cannot use malloc s we have not yet covered it in class. The program has to continue to take user input until the user enters ^D. We're using GCC so I have it set up to use variable length arrays and I've managed to get the program to find and replace a single instance of oldstring in the user input. However, on occasion the program will output some garbage characters and I am not sure why. I assume it is a memory allocation error or the program is reading past where I want it to read. The code is below:
#include <stdio.h>
#include <string.h>
int isMatch(char * os, char * us){
int i;
char temp[strlen(os)];
for(i=0; i<strlen(us); i++){
int k=0;
for(int j=i; j<i+strlen(os); j++){
temp[k]=us[j];
k++;
}
if(strcmp(temp, os)==0){
return 1;
}
else{
return 0;
}
}
}
void replace(char * os, char * us, char * ns, int loc){
char out[strlen(us) - (strlen(os) - strlen(ns))];
int i;
for(i=0; i<loc; i++){
out[i]=us[i];
}
int k=0;
for(i=loc; i<loc+strlen(ns); i++){
out[i]=ns[k];
k++;
}
k=0;
for(i=loc+strlen(ns); i<strlen(us)-(strlen(os)-strlen(ns)); i++){
out[i]=us[loc+strlen(os)+k];
k++;
}
printf("%s\n", out);
}
int main(int argc, char * argv[]){
char input[100];
int i;
char c;
int match;
while(1){
if(scanf("%c", &c)==EOF){
break;
}
if((input[0]=c) != '\n'){
for(i=1; i<100; i++){
scanf("%c", &input[i]);
if(input[i]=='\n'){
break;
}
}
}
for(i=0; i<100; i++){
match = isMatch(argv[1], &input[i]);
if(match == 1){
replace(argv[1], input, argv[2], i);
}
if(input[i]=='\n'){
break;
}
}
}
}
I call the program with ./a.out aa b for example.
I then enter helaalo and the program spits out helblo which is correct. I then enter libraary and the program outputs librbry followed by some random characters on new lines. I then enter caar and the program outputs cbr followed by even more random letters on new lines. A screenshot of this behavior is included.
Since you can't use malloc, you can force to add terminating \0 for the end of input string and end of out string,
// input
for(i=1; i<100; i++){
scanf("%c", &input[i]);
if(input[i]=='\n'){
input[i] = '\0'; // add terminating \0 for input
break;
}
}
// out
for(i=loc+strlen(ns); i<strlen(us)-(strlen(os)-strlen(ns)); i++){
out[i]=us[loc+strlen(os)+k];
k++;
}
int len = strlen(us)-(strlen(os)-strlen(ns));
out[len] = '\0'; // for out termiante \0
printf("%s\n", out);
The problem is coming from your the way you are filling your input buffer. You don't add a \0 at the end of the string.
There is also an other "problem", when you declare you array out if you want a dynamic size you need to use a malloc. how you are declaring it will not have a dynamic size , the size of the array will be calculated at compilation time. Just to keep it in mind.

Different assigning methods of char arrays

Can anyone point out what's wrong with this code and why the first print case won't work but the second won't? Thanks!
char source[] = "hello folks";
char destination[11];
strcpy(destination, source);
for(int i = 0; source[i]; i++) {
printf("%c" , source[i]);
}
printf("\n");
for(int i = 0; destination[i]; i++) {
printf("%c" , destination[i]);
}
printf("\n");
You declare destination as an array of 11 chars, but then you use strcpy to copy 12 chars from source into it. Every string needs to have a NUL terminator, which is part of the string, so it is important to count it when figuring out the size of an array needed to hold the string.

I keep getting segmentation fault: 11 when trying to compare two arrays in C

I am trying to compare two arrays that hold data and if one array matches data in another array I want it to print to the screen which data it found a match on. I keep getting a segmentation fault: 11 and it also prints match 1000 which is wrong. Normally I'm reading in a csv file that holds a lot more data but for the sake of testing and simplifying it I've just created smaller arrays of similar data. Any help would be great.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define BUFFER_SIZE 100
int main(int argc, char *argv[]){
//Setting up variables
int i,j,count;
/*Setting up file pointer and opening file
//FILE *fp;
//fp = fopen("csvTest.csv","r");
//if(!fp){
//printf("File did not open");
}*/
//Making a string buffer and getting the data from the CSV
//and placing it into the buffer
char buff[BUFFER_SIZE] = "1000,cap_net_raw,cap_sys_admin,cap_setpcap";
//fgets(buff, 100, fp);
//fclose(fp);
//Finding out how many caps there are based off commas
for(i=0;buff[i] != '\0';i++){
count += (buff[i] == ',');
}
printf("Number of caps: %d\n", count);
//Using strtok (string token) to split the buffer string at the comma
//Setting up an array to hold the data after the split
char *tokptr = strtok(buff,",");
char *csvArray[count+1];
i = 0;
while(tokptr != NULL){
csvArray[i++] = tokptr;
tokptr = strtok(NULL, ",");
}
//Printing the data from the array
printf("EUID & CAPS from CSV file: \n");
for(j=0; j < i; j++){
printf("%s\n", csvArray[j]);
}
//Getting all current caps and storing them into an array
//cap_t caps = cap_get_proc();
//char *capList[CAP_LAST_CAP] = {};
char *capList[7] = {"cap_chown","cap_setfcap","cap_net_raw","cap_sys_admin",
"cap_setpcap","cap_net_admin","cap_sys_overide"};
/*for(i = 0; i < CAP_LAST_CAP; i++){
//capList[i] = cap_to_name(i);
}*/
//Setting the caps by comparing the csv array and checking to see if
//there is a match in the caplist, if there is then it will set the cap
for(i = 0; i < count; i++){
for(j = 0; j < 37; j++){
if(strcmp(csvArray[i],capList[j]) == 0){
printf("Set cap to %s\n", csvArray[i]);
}
}
}
return 0;
}
I found two problems:
count is not initialized. When you are counting commas, you start from an unpredictable value. This is undefined behavior.
The loop over capList goes out of bounds. The j loop goes up to 37, but the array is only of size 7. This is also undefined behavior.
Fixing those two problems, your program appears to work (at least, it doesn't crash -- whether it has the behavior you intend, I can't be sure).

Resources