Creating a 3D Array from an input file? - c

I want to store the following lines from an input file into a 3D Array (excluding the first line.) The first line represents the number of following lines.
3
4 9368 86 843 23224
4 7323 2 2665 2665
8447 47 843 5278 8378 2273
My problem is if I use fscanf, there is no way to tell when there is a newline. Therefore I can't stop scanning and go to the next index in the outermost array. If I use fgets and sscanf, I can only read in the first string of each line (in this case, 4 then 4 then 8447.)
That is because fgets processes an entire line as one string (1D Array,) when I want each line to be processed as a 2D array, and then each stored in an outermost array, resulting in a 3D array.
How can I solve this problem?

You can use sscanf() combined with fgets() to parse one number at a time. You can do it by advancing a pointer into your string as you parse each number.
while (fgets(buf, sizeof(buf), infile) != 0) {
const char *p = buf;
size_t len = strlen(buf);
int val;
int n;
while (sscanf(p, "%d%n", &val, &n) == 1) {
/*...do something with val */
p += n;
if (p >= buf+len) break;
}
}
The %n directive provides the number of bytes consumed thus far in the scan.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char array[16][16][16];
char line[256];
FILE *fp = fopen("data.txt", "r");
fgets(line, sizeof(line), fp);
int row = atoi(line);
int i;
for(i = 0;i<row;++i){
int col = 0;
char *p;
fgets(line, sizeof(line), fp);
for(p = strtok(line, " \t\n");p;p=strtok(NULL, " \t\n")){
strcpy(array[i][col++], p);
}
array[i][col][0] = '\0';
}
fclose(fp);
{//check
for(int i=0;i<row;++i){
for(int j=0;array[i][j][0];++j)
printf("%s ", array[i][j]);
printf("\n");
}
}
return 0;
}

Related

Find text inside the beg and end () parentheses in textile and read/print into a buffer. IN C

I am new to C and am getting very frustrated with learning this language. Currently I'm trying to write a program that reads in a program textfile, reads and prints all the string literals, and tokens each on separate line. I have most of it except for one snag. within the text file there is a line such as: (..text..). I need to be able to search, read and print all the text is inside the parentheses on it's own line. Here is an idea I have so far:
#define KEY 32
#define BUFFER_SIZE 500
FILE *fp, *fp2;
int main()
{
char ch, buffer[BUFFER_SIZE], operators[] = "+-*%=", separators[] = "(){}[]<>,";
char *pus;
char source[200 + 1];
int i, j = 0, k = 0;
char *words = NULL, *word = NULL, c;
fp = fopen("main.txt", "r");
fp2 = fopen ("mynewfile.txt","w") ;
while ((ch = fgetc(fp)) != EOF)
{
// pus[k++] = ch;
if( ch == '(')
{
for ( k = 0;, k < 20, K++){
buffer[k] = ch;
buffer[k] = '\0';
}
printf("%s\n", buffer)
}
....
The textfile is this:
#include <stdio.h>
int main(int argc, char **argv)
{
for (int i = 0; i < argc; ++i)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
}
So far I've been able to read char by char and place it into a buffer. But this idea just isn't working, and I'm stumped. I've tried dabbling with strcopy(), ands strtok, but they all take char arrays. Any ideas would be appreciated thank you.
Most likely the best way would be to use fgets() with a file to read in each line as a string (char array) and then delimit that string. See the short example below:
char buffer[BUFFER_SIZE];
int current_line = 0;
//Continually read in lines until nothing is left...
while(fgets(buffer, BUFFER_SIZE - 1, fp) != NULL)
{
//Line from file is now in buffer. We can delimit it.
char copy[BUFFER_SIZE];
//Copy as strtok will overwrite a string.
strcpy(copy, buffer);
printf("Line: %d - %s", current_line, buffer); //Print the line.
char * found = strtok(copy, separators); //Will delmit based on the separators.
while(found != NULL)
{
printf("%s", found);
found = strtok(NULL, separators);
}
current_line++;
}
strtok will return a char pointer to where the first occurrence of a delimiter is. It will replace the delimiter with the null terminator, thereby making "new" string. We can pass NULL to strtok to tell it to continue where it left off. Using this, we can parse line by line from a file based on multiple delimiters. You could save these individual string or evaluate them further.

In C strtok() is working for "," (commas) but not for spaces " ". Getting a seg fault when working with spaces

I'm new here. This is my first post!
So I wrote code in C to take in a comma separated text file and read it into a 2D array. I used strtok() for that. It worked. Below is the code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
FILE *data = fopen(argv[1], "r");
if (data == NULL)
{
printf("Could not open 11.txt\n");
return 1;
}
char table[20][20][3];
char buffer[60];
int i = 0;
while (fscanf(data, "%s", buffer) != EOF)
{
int j = 0;
for (char *s = strtok(buffer, ","); s != NULL; s = strtok(NULL, ","))
{
for (int k = 0; k < strlen(s) + 1; k++)
{
table[i][j][k] = s[k];
}
j++;
}
i++;
}
printf("%s\n", table[19][0]);
return 0;
}
The data I'm trying to read into the 2D array looks like:
08,02,22,97
49,49,99,40
81,49,31,73
52,70,95,23
It is a 20x20 matrix with numbers separated by commas.
The above program works fine (I'm printing out an element of this 2D array to check if the program is working). But when the numbers are separated by spaces:
08 02 22 97
49 49 99 40
81 49 31 73
52 70 95 23
and when I replace the "," with " " in the strtok() function I get a seg fault. I'm at a loss for why this is the case.
Thank you for the help!
EDIT:
The bug has been fixed!
#Vlad From Moscow very correctly pointed out that fcanf() is not the correct function to use to read into a buffer a string with white space. He suggested instead to use fgets() which can read white space. I was still facing a seg fault because the first token returned by strtok() was a pointer to NULL. I'm not sure why its doing that because when I fed strtok() an array with the same string without using fgets() in a while loop as shown, there were no issues:
char str[] = "08 02 22 97";
So to fix this I put a condition in the for loop to skip to the next iteration if the strtok() returned a NULL pointer.
The second issue was that my buffer wasn't large enough (spaces are 4 bytes compared to 1 byte for a char). Fixing these two issues I got the code to work!
Below is the corrected code:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
FILE *data = fopen(argv[1], "r");
if (data == NULL)
{
printf("Could not open 11.txt\n");
return 1;
}
char table[20][20][3];
char buffer[61];
int i = 0;
while (fgets(buffer, sizeof(buffer), data) != NULL)
{
int j = 0;
for (char *s = strtok(buffer, " "); s != NULL; s = strtok(NULL, " "))
{
if (s == NULL)
{
continue;
}
else
{
for (int k = 0; k < strlen(s) + 1; k++)
{
table[i][j][k] = s[k];
}
j++;
}
}
i++;
}
printf("%i\n", atoi(table[19][19]));
return 0;
}
The function fscanf with the format specifier %s reads data until a white space character is encountered. So you can not use the function fscanf as you are using it in the while statement
while (fscanf(data, "%s", buffer) != EOF)
to read strings containing embedded white spaces.
Instead use the standard C function fgets.
Pay attention to that instead of this for loop
for (int k = 0; k < strlen(s) + 1; k++)
{
table[i][j][k] = s[k];
}
you could use the standard string function strcpy as for example
strcpy( table[i][j], s );
Also this call
printf("%s\n", table[20][0]);
invokes undefined behavior because for an array declared like
char table[20][20][3];
the valid range of the first index is ]0, 20 ). That is you may not use the value 20 as the index.

C loop to read lines of input

I want to create a program in C that takes an arbitrary number of lines of arbitrary length as input and then prints to console the last line that was inputted. For example:
input:
hi
my name is
david
output: david
I figured the best way to do this would be to have a loop that takes each line as input and stores it in a char array, so at the end of the loop the last line ends up being what is stored in the char array and we can just print that.
I have only had one lecture in C so far so I think I just keep setting things up wrong with my Java/C++ mindset since I have more experience in those languages.
Here is what I have so far but I know that it's nowhere near correct:
#include <stdio.h>
int main()
{
printf("Enter some lines of strings: \n");
char line[50];
for(int i = 0; i < 10; i++){
line = getline(); //I know this is inproper syntax but I want to do something like this
}
printf("%s",line);
}
I also have i < 10 in the loop because I don't know how to find the total number of lines in the input which, would be the proper amount of times to loop this. Also, the input is being put in all at once from the
./program < test.txt
command in Unix shell, where test.txt has the input.
Use fgets():
while (fgets(line, sizeof line, stdin)) {
// don't need to do anything here
}
printf("%s", line);
You don't need a limit on the number of iterations. At the end of the file, fgets() returns NULL and doesn't modify the buffer, so line will still hold the last line that was read.
I'm assuming you know the maximum length of the input line.
This one here will surely do the job for you
static char *getLine( char * const b , size_t bsz ) {
return fgets(b, bsz, stdin) );
}
But remember fgets also puts a '\n' character at the end of buffer so perhaps something like this
static char *getLine( char * const b , size_t bsz ) {
if( fgets(b, bsz, stdin) ){
/* Optional code to strip NextLine */
size_t size = strlen(b);
if( size > 0 && b[size-1] == '\n' ) {
b[--size] = '\0';
}
/* End of Optional Code */
return b;
}
return NULL;
}
and your code needs to be altered a bit while calling the getline
#define BUF_SIZE 256
char line[BUF_SIZE];
for(int i = 0; i < 10; i++){
if( getLine(line, BUF_SIZE ) ) {
fprintf(stdout, "line : '%s'\n", line);
}
}
Now it is how ever quite possible to create function like
char *getLine();
but then one needs to define the behavior of that function for instance if the function getLine() allocates memory dynamically then you probably need use a free to de-allocate the pointer returned by getLine()
in which case the function may look like
char *getLine( size_t bsz ) {
char *b = malloc( bsz );
if( b && fgets(b, bsz, stdin) ){
return b;
}
return NULL;
}
depending on how small your function is you can entertain thoughts about making it inline perhaps that's a little off topic for now.
In order to have dynamic number of input of dynamic length, you have to keep on reallocating your buffer when the input is of greater length. In order to store the last line, you have to take another pointer to keep track of it and to stop the input from the terminal you have to press EOF key(ctrl+k). This should do your job.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *get_last_line(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
char *str, *last_str = NULL;
int ch;
size_t len = 0, last_len = 0;
str = realloc(NULL, sizeof(char)*size);//size is start size
if(!str)return str;
while(ch=fgetc(fp)){
if(ch == EOF){
break;
}
if(ch == '\n'){
str[len]='\0';
last_len = len;
last_str = realloc(last_str,sizeof(char)*last_len);
last_str[last_len]='\0';
//storing the last line
memcpy(last_str,str,sizeof(char)*last_len);
str = realloc(NULL, sizeof(char)*size);//size is start size
len = 0;
}
else {
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(char)*(size+=16));
if(!str)return str;
}
}
}
free(str);
return last_str;
}
int main(void){
char *m;
printf("input strings : ");
m = get_last_line(stdin, 10);
printf("last string :");
printf("%s\n", m);
free(m);
return 0;
}

Storing strings from a text file into a two dimensional array

I'm working on a project using C and for the project I must read in a text file and store each word into an array. I also have to remove the punctuation off the words, so I need to use a 2-Dimensional array in order to edit the words. I am having trouble figuring out how to get the words in the 2-D array it self. This is what I have done so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1001
#define LINES 81
int main(void) {
int stringSize;
int i =0;
char *x[MAX][LINES];
char str[MAX];
char y[MAX];
FILE *fp;
fp = fopen("TwoCitiesStory.txt","r");
if(fp == NULL) {
printf("Cannot open file.\n");
exit(1);
}
while(!feof(fp)) {
for(i=0;i<MAX;i++){
fscanf(fp,"%s",x[i][LINES]);
}
}
return 0;
}
The following line
char *x[MAX][LINES];
declared a 2D array of pointers. What you need is just a 2D array of characters.
char x[MAX][LINES];
The code for reading the words can be simplified to:
while( i < MAX && fscanf(fp, "%80s", x[i]) == 1 )
{
++i;
}
Read the whole line using fgets()
Store the read line into the 2D array
The whole code looks like
char x[row][col];
char buf[300];
int i=0,j=0;
memset(x,0,sizeof(x));
while(fgets(buf,sizeof(buf),fp))
{
size_t n = strlen(buf);
if(n>0 && buf[n-1] == '\n')
buf[n-1] = '\0';
if(i>= row && n> col)
break;
strcpy(x[i],buf);
i++;
}
Edits:
If you need each word separately in the array.
buf is being used to read the whole line.
strtok() is used to break the line into words with space as delimiter.
Then store each word in each row.
size_t n;
while(fgets(buf,sizeof(buf),fp))
{
char *p = strtok(buf," ");
while( p != NULL)
{
n = strlen(p);
if(i>= row && n> col)
break;
strcpy(x[i],p);
i++;
p = strtok(NULL," ");
}
}
If you want to print out the array go for
int i;
for(i=0;i<row;i++)
printf("%s\n",x[i]);
Why feof() is wrong

Storing the buffer of fgets in Array

I'm new to C (coming from Java) and naturally that poses some difficulties. I would like to write just a short program that reads in char-Arrays from stdin and stores the individual strings in an array. After reading in the strings I just want to have them printed out, but that's when it gets really confusing for me.
Here's my code:
#include <stdlib.h>
#include <stdio.h>
int main(){
char **stringarray[2];
char buffer[5];
int i = 0;
while( i < 2 && fgets(buffer, 5, stdin) != NULL){
char *tmp = buffer;
stringarray[i] = &tmp;
i++;
}
for(int i = 0; i < 2; i++){
printf("%s\n", &stringarray[i]);
}
return 0;
}
The first part does in fact compiles (i.e. the part before the print out). I understand that my stringArray has to be an array of char pointers, because that's what a char array basically is in c. It's a pointer to the first character. At first I just wrote
while( i < 2 && fgets(buffer, 5, stdin) != NULL){
stringarray[i] = buffer;
i++;
}
which also compiled, but of course then I have one pointer that points to buffer, which will only save the last string that has been read.
What do I have to do that I can store a simple array of strings?
I suggest you change your code as following.
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* to use strdup function */
int main(){
char *stringarray[2]; /* I don't understand why you use pointer to pointer than pointer, char **stringarray[2]; */
char buffer[6]; /* I suggest 6 than 5, because string has terminate byte in C */
int i = 0;
while( i < 2 && fgets(buffer, 5, stdin) != NULL){
stringarray[i] = strndup(buffer, 5);
i++;
}
for(int i = 0; i < 2; i++){
printf("%s\n", stringarray[i]); /* changed stringarray */
}
return 0;
}
char **stringarray[2]; is like char ***stringarray because an array is like a pointer to the first value of the array.
printf wants a char* and &stringarray[i] is a char**
if a string is an array then an array of strings is an array of array.
So the code is :
int main()
{
char stringarray[2][5];//array of (array of char)
char buffer[5];
int i = 0;
while( i < 2 && fgets(buffer, 5, stdin) != NULL)
{
strcpy(stringarray[i],buffer); //copies the buffer into the string array
i++;
}
for(i = 0; i < 2; i++)
{
printf("%s\n", stringarray[i]);
}
return 0;
}
If you didn't want to use buffer you could just writte :
while( i < 2 && fgets(stringarray[i], 5, stdin) != NULL)
{
i++;
}
Note that you get 5 characters, the last one will be the NUL terminator \0. And because you have to press enter to validate, the one before \0 will be Line Feed\n. And you will only have 3 characters you really wanted.
You can do it using dynamic allocation technique as below .
#include<stdio.h>
#include<malloc.h>
#include <stdlib.h>
int main()
{
int num;
int len=0;
int i;
printf("Enter the number of elements to be entered ");
scanf("%d",&num);
//Allocate memory for the array of strings
char **var=(char **)malloc(num * sizeof(char *));
for(i=0;i<num;i++)
{
printf("Enter the string : ");
//get strings using getline
getline(&var[i],&len,stdin);
}
for(i=0;i<num;i++)
{
printf("String %d : %s \n",i,var[i]);
}
free(var);
}

Resources