how to read integers from a string that are separated by space - c

in the text file it'll say something like this:
12 4 23 76
7 3 12 54
1 54 2 67
...
int arr[26];
int arr2[26];
int arr3[26];
int main(){
fp = fopen ("myfile.txt", "r");
while (fgets(store, sizeof(store), fp)){
//I tried using scanf but I couldn't get it to work
printf("%s", store); //prints out a line
}
}
I know that the 'store' has the string that I want to work with.
how can I grab the integers from 'store' that are separated by space and put them into an array?
so I would want
arr[0]=12 arr[1]=4 arr[2]=23 arr[3]=76,
arr2[0]=7 arr2[1]=3 arr2[2]=12 arr2[2]=65,
arr3[0]=1 arr3[1]=54 arr3[2]=2 arr3[3]=67

you can use strtok() and atoi() function if string format is guaranteed.
here's draft of code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int arr[3][26];
char store[100];
char *split;
int i, j;
int main(){
i = 0;
FILE* fp = fopen ("myfile.txt", "r");
while (fgets(store, sizeof(store), fp)){
printf("%s", store); //prints out a line
split = strtok(store, " ");
j = 0;
while(split) {
arr[i][j++] = atoi(split);
split = strtok(NULL, " ");
}
i++;
}
for(i = 0; i < 3; i++) {
for(j = 0; j < 4; j++) {
printf("%2d ", arr[i][j]);
}
puts("");
}
}
I hope that you can utilize this code for what you want.
-> I fixed code which is able to run.
you can modify this code because I tested and it worked.
I'm not sure which point you struggled, but I suggest you to check out how to use those functions in web.

the code posted by ChangHo is pretty accurate barring a few corrections.
Since the data contained in the text file, seems to contain blank lines, the primary fix is to ensure that these lines are ignored.
I notice in your comment, that when you try printing the vales after "strtok", you notice 0s.That's because the value of the variable "j" has been incremented....And is yet to be assigned a new value.....
arr[i][j++] = atoi(split);// j has been incremented
split = strtok(NULL, " ");
printf("%d\n", arr[i][j]);//displays 0,since "j" is yet to be assigned a value
All in all, here is the updated version of the code posted....
Please see the comments......
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int arr[3][26];
char store[100];
int i = 0;
int j = 0;
char *split;
int main(){
FILE *fp;
fp = fopen ("test.txt", "r");
while (fgets(store, sizeof(store), fp)){
if(strlen(store) == 1)//When fgets returns just the newline character
continue; //skip the line
printf("%s", store); //prints a line
split = strtok(store," ");
j = 0;
while(split != NULL){
arr[i][j] = atoi(split);
split = strtok(NULL," ");
printf("%d\n", arr[i][j]);//print value in array before j is incremented
j++;
}
arr[i][j] = '\0';//terminate the sub array with the NULL character
i++;
}
//print the result
for(int i = 0;i<3;++i){
for(int j = 0;arr[i][j] != '\0';++j)
printf("%d ",arr[i][j]);
putchar('\n');
}
fclose(fp);
}

Related

Reading words and storing them in 2-D array in C

I am trying to write a program that reads lines word by word and puts each word in an array (later I want to do some operations on those words but this isn't an issue now) and in the output there should be a number of words in each line. For example:
input:
good morning my neighbors!
how are you?
output:
4
3
Here is my code:
#include <stdio.h>
#include <string.h>
int main()
{
char word[100];
char wordArray[100][100];
int count = 0;
for(;scanf("%s", word)!=EOF;)
{
strcpy(wordArray[count], word);
count++;
}
printf("%d", count);
return 0;
}
But it gives me just 7 in the output (number of all words on both lines). If I put printf function inside the for loop then I get 1234567 as an output. How do I make it count words on one line and print it then set the count to zero and start over on the next line?
You should use fgets or getline because scanf reads word by word not all words in one line.
The code:
#include <stdio.h>
#include <string.h>
#define SIZE 100
int main()
{
char wordArray[SIZE][SIZE];
int count[SIZE];
int c = 0;
while(fgets( wordArray[c], SIZE, stdin) && c < SIZE)
{
for(int i = 0; wordArray[c][i] != '\0' ; i++) {
// remove enter character at the end of each line, not necessary in this case but mabe later when you work with all works
wordArray[c][strcspn ( wordArray[c], "\n" )] = '\0';
if (wordArray[c][i] == ' ') {
count[c]++; // increase the number of words if we meet space character
}
}
c++;
}
for (int i = 0; i < c; i++) //print all the counts
printf("%d", count[i] + 1);
return 0;
}
Here I used fgets to get line by line from stdin.
The code actually count the spaces in the line and add 1 to them. I also did NOT used string.h.
#include <stdio.h>
#define SIZE 100
int main()
{
int i=0;
char lines[SIZE][SIZE];
int count[SIZE]={0};
while(i<SIZE){
fgets(lines[i], SIZE, stdin);
if (lines[i][0]=='\n') break;
i++;
}
for(int j=0; j<i; j++){
char *x=lines[j];
while(*x!='\0') {
if (*x==' ') count[j]++;
x++;
}
printf("%d\n", count[j]+1);
}
return 0;
}
It gives you 7 because count is never reseted. I would store the counts to print later, this could be done with an array, the 1234567 is normal if it's inside the cycle it will print count for every word scaned. If you use "%d " with a space you'll have 1 2 3 4 5 6 7.
The following program takes 5 lines from the user, counts the words in each line and stores the counts in an array, using scanf and strtok to count the words:
Demo
#include <stdio.h>
#include <string.h>
#define SIZE 5
#define LENGTH 100
int main()
{
char word[LENGTH];
char wordArray[SIZE][LENGTH];
int count[SIZE] = {0}; //array to store the counts
const char delimiter[] = " ";
char *token;
printf("Insert %d phrases:\n", SIZE);
// %99[^\n] specifier also to avoid buffer overflow and read till newline
for (int i = 0; i < SIZE && scanf(" %99[^\n]", wordArray[i]) == 1; i++)
{
strcpy(word, wordArray[i]);
token = strtok(word, delimiter);
while (token != NULL)
{
count[i]++;
token = strtok(NULL, delimiter);
}
}
for (int i = 0; i < SIZE; i++) {//print all the counts
printf("string %d - \"%s\" - ", i + 1, wordArray[i]);
printf("%d words\n", count[i]);
}
return 0;
}

How can I duplicate a letter in a string?

I want to write a program where it duplicates every letter in a given string.
For example, if the input is abc then the output would be aabbcc.
How can I do this?
Here is my code so far. It only copies the string:
#include <stdio.h>
int main () {
char str_in[100];
char str_out[200] = "";
int i;
printf("Enter a word: ");
scanf("%s", str_in);
for (i = 0; i < sizeof(str_in); i++) {
str_out[i] += str_in[i];
}
printf("Duplicated word: %s", str_out);
return 0;
}
For starters the destination character array should be at least two times larger than the source array.
The loop that performs the copying can look the following way
size_t j = 0;
for ( size_t i = 0; str_in[i] != '\0'; i++ )
{
str_out[j++] = str_in[i];
str_out[j++] = str_in[i];
}
str_out[j] = '\0';
This is one way to do what you want - since you know that the two indexes in str_out that you want to access correspond to the ith and i+1th positions of str_in:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
char str_in[SIZE];
char str_out[SIZE*2];
int i, len;
printf("Enter a word: ");
scanf("%s", str_in);
len = strlen(str_in);
for (i = 0; i < len; i++) {
str_out[i*2] = str_in[i];
str_out[i*2+1] = str_in[i];
}
str_out[i*2] = '\0';
printf("Duplicated word: %s\n", str_out);
return EXIT_SUCCESS;
}
You could also use another variable and update inside the loop as such:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main(void)
{
char str_in[SIZE];
char str_out[SIZE*2];
int i, j, len;
printf("Enter a word: ");
scanf("%s", str_in);
len = strlen(str_in);
for (i = 0, j = 0; i < len; i++, j += 2) {
str_out[j] = str_in[i];
str_out[j+1] = str_in[i];
}
str_out[j] = '\0';
printf("Duplicated word: %s\n", str_out);
return EXIT_SUCCESS;
}
As a side note, it's best to #define your constants instead of having them in your code.
I would suggest only allocating the amount of memory you need:
char *str_out = malloc(strlen(str_in) + 1);
and then using another loop variable that counts by 2 each time so you have 2 times as much space for every character in your loop.
If you do that, you should also put + 1 next to the new loop variable to copy it to the current and next elements of the string, thereby duplicating the characters.
I would also advise you to use size_t for your loop variables to match the return of str_len.
Here I have implemented my suggestions:
size_t str_ctr;
size_t str_ctrx2;
size_t in_str_len = strlen(in_str)
/* ... */
for( str_ctrx2 = str_ctr = 0;
str_ctr < in_str_len;
str_ctr++, str_ctrx2 += 2 )
{
out_str[str_ctrx2] = in_str[str_ctr];
out_str[str_ctrx2 + 1] = in_str[str_ctr];
}
/* null-terminate the string */
out_str[str_ctrx2] = '\0';
I would also like to mention that you forget to null-terminate your string in your program. I have made a comment about that and have shown you how to do it above.
#include <stdio.h>
int main () {
char str_in[100];
char str_out[200] = "";
int i, j;
printf("Enter a word: ");
scanf("%s", str_in);
j=0;
for (i = 0; i < sizeof(str_in); i++) {
str_out[i] = str_in[j];
str_out[i+1] = str_in[j];
i++;
j++;
}
printf("Duplicated word: %s", str_out);
return 0;
}

Reading file content line by line into a matrix

I was trying to write a function that could copy a text file content line by line to a matrix, so this is what I came up with:
#include <stdio.h>
#include <stdlib.h>
#define rows 5
#define columns 12
void file_to_matrix(char *matrix[]){
FILE *file = fopen("swamp.txt", "r");
if(file==NULL){
printf("File error");
exit(1);
}
int y=0;
for(int x=0; (matrix[y][x]=fgetc(file))!=EOF; ++x){
if(matrix[y][x]=='\n'){
++y;
x=0;
}
}
fclose(file);
}
int main(){
char *matrix[rows];
file_to_matrix(matrix);
for(int i=0; i<5; ++i){
for(int j = 0; j < 11; j++){
printf("%c", matrix[i][j]);
}
printf("\n");
}
}
I tried to compile and run it on Windows and Linux but the only thing that it manages to do is giving me errors that are practically useless like:
"Stopping due to fatal error: NullReferenceException: Object reference not set to an instance of an object"
or
"Segmentation fault (core dumped)"
You have to allocate memory for each element of matrix. This is the same exact mistake as writing:
char *s = "string";
As the first act of the program, loop through matrix, and call malloc for each cell:
int i;
for (i = 0; i < 5; ++i)
if (!(matrix[i] = malloc(MAXLEN))) [
perror("malloc");
exit(EXIT_FAILURE);
}
Note: we check the return value of malloc to ensure no errors have occurred.
with your code, i think the matrix in the file will restricted (you define rows=5 and columns=12). so i think again to write a code that can be flexible, no need to set max row or column again. here we go
#include <stdio.h>
#include <stdlib.h> //malloc realloc
//file read function. returning string with splitted new line
//ex: (note: newline is '\n' (ENTER))
//test.txt:
//10 20 30(space)(newline)
//40 50 60(space)(newline)
void file_to_matrix(char *filename)
{
FILE * file = fopen(filename, "r");
char *buff = (char*)malloc(sizeof(char)); //temp string
int *matrix_row = (int*)malloc(sizeof(int)); //temp matrix row
int **MATRIX = (int**)malloc(sizeof(int*)); //this will become the final matrix
int index_buff = 0, index_MATRIX = 0, index_matrix_row = 0;
while (1)
{
char c = getc(file);
if (c==EOF)
{
break;
}
if (c=='\n') //if c meet newline, then add the matrix row to final matrix
{
(*(MATRIX+index_MATRIX)) = matrix_row;
index_MATRIX++;
MATRIX = realloc(MATRIX, sizeof(MATRIX)*(index_MATRIX+1));
matrix_row = (int*)malloc(sizeof(int));
index_matrix_row = 0;
printf("\n");
continue;
}
if (c==' ') //if c meet space, then buff wil converted to int
{
int num = atoi(buff);
printf("%d ", num);
(*(matrix_row+index_matrix_row)) = num;
index_matrix_row++;
matrix_row = realloc(matrix_row, sizeof(int)*(index_matrix_row+1));
free(buff);
buff = (char*)malloc(sizeof(char));
index_buff=0;
continue;
}
//add buff with c
(*(buff+index_buff))=c;
index_buff++;
buff = realloc(buff, sizeof(char)*(index_buff+1));
}
fclose(file);
//clearing the dynamic memory
free(buff);
for (int i = 0; i < index_MATRIX; i++)
{
free(MATRIX[i]);
}
}
int main()
{
file_to_matrix("test.txt");
return 0;
}
test.txt:
10 20 30
40 50 60
70 80 90
if you confused with the test.txt format, i will explain again:
10 20 30(space)(newline)
30 40 60(space)(newline)
70 80 90(space)(newline)
Thank you for your replies, I think your solutions are very clever but I was looking to an easier one.
After a little bit of trial and error I think I found a solution that it isn't very generalized but it's simple and it seems to work fine:
#include <stdlib.h>
#include <stdio.h>
#define ROWS <n of rows>
#define COLS <n of columns>
void file_to_matrix(int rows, int cols, char matrix[rows][cols], char file_path[]){
FILE *file = fopen(file_path, "r");
if(file==NULL){
printf("File error");
exit(1);
}
int y=0;
for(int x=0; (matrix[y][x]=getc(file))!=EOF; ++x){
if(matrix[y][x]=='\n'){
matrix[y][x]='\0';
++y;
x=-1;
}
}
fclose(file);
}
int main(){
char matrix[ROWS][COLS+2];
file_to_matrix(ROWS, COLS+2, matrix, "file path");
for(int i=0; i<=ROWS; ++i){
printf("%s\n", matrix[i]);
}
}
Thank you again for your answers

Reading in Large Integer txt file into 2D array

Attempting to create a program that reasons in a large Text File and filled them into Rows + Columns. Eventually I'll have to computer best path but having trouble just implementing an Array that can store the values.
#include <stdio.h>
#include <stdlib.h>
//max number of characters to read in a line. //MAXN=5 means 4 chars are read, then a \0 added in fgets. See reference for functionality
#define MAXN 100L
int main(void) //char** argv also ok {
int i=0, totalNums, totalNum,j=0;
size_t count;
int numbers[100][100];
char *line = malloc(100);
FILE* inFile ;
inFile = fopen("Downloads/readTopoData/topo983by450.txt", "r"); //open a file from user for reading
if( inFile == NULL) { // should print out a reasonable message of failure here
printf("no bueno \n");
exit(1);
}
while(getline(&line,&count, inFile)!=-1) {
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
i++;
}
totalNums = i;
totalNum = j;
for(i=0;i<totalNums; i++){
for(j=0;j<totalNum;j++){
printf("\n%d", numbers[i][j]);
}
}
fclose(inFile);
return 0;
}
count does not tell you how many numbers there are. Further: sscanf(line, "%d", &numbers[i][j]); will just scan the same number every time.
So this
for(;count>0; count--,j++)
sscanf(line, "%d", &numbers[i][j]);
should be something like:
j = 0;
int x = 0;
int t;
while(sscanf(line + x, "%d%n", &numbers[i][j], &t) == 1)
{
x += t;
++j;
}
where x together with %n helps you move to a new position in the string when a number has been scanned.
Here is a simplified version that scans for numbers in a string:
#include <stdio.h>
int main(void) {
char line[] = "10 20 30 40";
int numbers[4];
int j = 0;
int x = 0;
int t;
while(j < 4 && sscanf(line + x, "%d%n", &numbers[j], &t) == 1)
{
x += t;
++j;
}
for(t=0; t<j; ++t) printf("%d\n", numbers[t]);
return 0;
}
Output:
10
20
30
40

reading variable length string arrays as ints

So I'm trying to read input from file that is formatted like this:
0 3 4 1
1 2 4
2
3
4 2
The piece of code that I've written here:
for (int i = 0; i < 5; i++){
if (fgets(line, MAX_LEN, in) != NULL){
printf("\n%s\n", line);
int length = strlen(line);
printf("line = %d\n", length);
for (int j = 2; j < length; j+=2){
char a;
a = line[j];
int u = a - '0';
printf("line[%d] = %d\n", j, u);
}
}
}
is very crude but handles the above single digit type input, however I need it to handle double digit values. I thought about using sscanf() but the line inputs can contain an arbitrary number of values so I don't know how many times to call it. Any assistance here would be great as I'm at a loss... Thank you!
I suggest you use strtol
Here is an example of how to use it :
#include <stdio.h>
#include <string.h>
int main() {
char str[20]="1 8 0 8 99"; // or your line
char *pt;
int numbers[10]; // array to read the numbers
int index = 0, i;
numbers[index] = strtol(str, &pt, 10); // decimal numbers
index++;
while(*pt !='\0' )
{
numbers[index] = strtol(pt, &pt, 10);
index++;
}
for(i=0; i<index; i++) printf("%d ", numbers[i]);
return 0;
}
The output in this example will be :
1 8 0 8 99
Now I let you the task of integrating strtol in your actual program good luck :)
for (int i = 0; i < 5; i++){
if (fgets(line, MAX_LEN, in) != NULL){
printf("\n%s\n", line);
int length = strlen(line);
printf("line = %d\n", length);
int len, u;
sscanf(line, "%*d%n", &len);
for (int j=len;sscanf(line + j, "%d%n", &u, &len)==1;j+=len){
printf("line[%d] = %d\n", j+1, u);//+1 : one space
}
}
}

Resources