Ignoring escape sequence in C - arrays

I need to enter a matrix of size NxN of integers.
My idea is to enter it as a sequence of chars into char array and proceed working with it.
Matrix is given into stdin all at once.
The problem is to ignore escape characters (e.g. "\n") and enter all NxN integers as one string where integers will be separated with space.
Matrix itself is copied from txt file.
Input must end when Enter key is pressed.
//en axample of what I'm trying to reach
char buff[512];
gets(buff);
/*1 2 9 10 25
4 3 8 11 24
5 6 7 12 23
16 15 13 14 22
17 18 19 20 21*/
printf("%s", buff);
/*1 2 9 10 25
4 3 8 11 24
5 6 7 12 23
16 15 13 14 22
17 18 19 20 21/*
I tried using gets but it ended reading symbols when "\n" is reached.
Initial code looks like this:
int main(){
int size;
printf("enter size of matrix >> ");
scanf("%d",&size);
int matrix[size][size];
char allNumbers[size][512];
for (int i = 0; i < size; i++){
fgets(allNumbers[i], 511, stdin);
}
printf("%s", allNumbers[2]);
return 0;
}
input:1 2 9 10 25\n 4 3 8 11 24\n 5 6 7 12 23\n 16 15 13 14 22\n 17 18 19 20 21\0
output:
1 2 9 10 25

Consider using one char array for input.
Generally do not use both scanf and fgets.
This uses fgets to read a line with the size and sscanf to parse the integer from the line.
The same array is used to read the lines pasted from the file.
The loop continues until an empty line is read.
It may be necessary to hit enter a few times to exit the loop.
This does not parse the integers from the file. sscanf can be used to accomplish that as well. strtol is another parsing option.
#include <stdio.h>
#include <stdlib.h>
int main ( void) {
char input[512] = "";
int size = 0;
int row = 0;
int col = 0;
int offset = 0;
int used = 0;
printf ( "enter size of matrix >> ");
fflush ( stdout);
if ( ! fgets ( input, sizeof input, stdin)) {
fprintf ( stderr, "problem fgets\n");
return 1;
}
if ( 1 != sscanf ( input, "%d", &size)) {
fprintf ( stderr, "problem sscanf for size\n");
return 2;
}
int matrix[size][size];
for ( row = 0; row < size; ++row) {
for ( col = 0; col < size; ++col) {
matrix[row][col] = 0;
}
}
row = 0;
printf ( "enter matrix values >> ");
while ( fgets ( input, sizeof input, stdin)){
if ( '\n' == input[0]) {
break;
}
printf ( "\nrow %d %s", row, input);
offset = 0;
if ( row < size) {
// parse integers from input;
}
++row;
}
for ( row = 0; row < size; ++row) {
for ( col = 0; col < size; ++col) {
printf ( "%4d ", matrix[row][col]);
}
printf ( "\n");
}
return 0;
}

Related

Input ints separated by whitespace and pass them to an int array

I'm trying to write a program in C where the user inputs a defined number of ints (in this case 5 ints) separated by whitespaces. Then, the input is stored in an int array so, lastly, it can be stored in a char array.
As an example of how the program is intended to work, when it asks for an input:
Input: 20 5 63 4 127
The output of the program should be:
Output: 20 5 63 4 127
This is what I've written so far, but I don't know how to get the input transformed into an int array. Note that I know the length of the input beforehand (in this case, as said above, 5 ints).
// Input: 20 5 63 4 127
// Ask for user input.
// Store the input in this int array.
int input_int_array[5];
unsigned char char_array[5];
for(int i=0;i<5;i++)
{
char_array[i]=input_int_array[i];
printf("%d ", char_array[i]);
}
// Should print: 20 5 63 4 127
You are probably expected to use scanf() to read user input as integers into an array of int:
#include <stdio.h>
int main() {
int input_int_array[5];
// Ask for user input.
printf("input 5 numbers: ");
for (int i = 0; i < 5; i++) {
// Store the input into the array.
if (scanf("%d", &input_int_array[i]) != 1)
return 1;
}
// Output the contents of the array:
for (int i = 0; i < 5; i++) {
printf("%d ", input_int_array[i]);
}
printf("\n");
return 0;
}

C fscanf input format

I have an input file that contains lines of the following format:
%s %d %d %d %lf %lf ... %lf\n
where the number of double values is unknown, but for my calculations I accept only first 15 of them.
The problem I can't figure out is, when I get to the line like this:
City0 28 2 2016 1 2 3 4 5 6 7 8 9 10
City1 28 2 2016 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
City2 1 3 2016 1 2 3 4 5
and I correctly assign respective values to a certain structure, I get the following:
City0 28 2 2016 Number of measures: 10
City1 28 2 2016 Number of measures: 15
16 17 18 19 Number of measures: 1
City2 1 3 2016 Number of measures: 5
How do I read(to nowhere)/ignore everything until I get to the end of the line, and then start reading the next line as usual? I need the following output:
City0 28 2 2016 Number of measures: 10
City1 28 2 2016 Number of measures: 15
City2 1 3 2016 Number of measures: 5
I tried this but ain't got any more ideas:
i=0; char character;
while (fscanf(fp, "%s %d %d %d", c.name, &c[i].date.day,
&c[i].date.month, &c[i].date.year)==4 && i<number_of_cities) {
while (fscanf(fp, "%lf", &c[i].measures[j])==1 && j<15) {
j++;
}
if (j==15) {
while (fscanf(fp, "%s", character)!='\n') {}
}
c[i].mnum = j;
j=0;
i++;
}
You can use fscanf() to read in an entire line of input, use sscanf() to scan the first four values, and use sscanf() again in a loop to read the double values. The trick here is to use the %n directive to save the position of the next read location in the string.
Here is an example. Note that size_t is used for array indices, as this is an unsigned integer type that is guaranteed to hold any array index. Also note that there is some error-checking when opening the file, and when scanning the beginning of a line. If the initial elements of the line do not match expected values, the program exits with an error message. This error-checking could be tightened up a bit; for example, if the year is entered as a floating point value, such as 2016.0, the input will be accepted, but the values stored in measures[] will begin with the 0 following the decimal point.
#include <stdio.h>
#include <stdlib.h>
struct Data {
char name[1000];
struct {
int day;
int month;
int year;
} date;
size_t mnum;
double measures[15];
};
int main(void)
{
size_t i = 0, j = 0;
char buffer[1000];
char *read_ptr = buffer;
int n_read = 0;
size_t number_of_cities = 3;
struct Data c[number_of_cities];
FILE *fp;
if ((fp = fopen("datafile.txt", "r")) == NULL) {
fprintf(stderr, "Unable to open file\n");
exit(EXIT_FAILURE);
}
while (fgets(buffer, 1000, fp) != NULL) {
if (sscanf(buffer, "%s %d %d %d %n", c[i].name, &c[i].date.day,
&c[i].date.month, &c[i].date.year, &n_read) != 4) {
fprintf(stderr, "Incorrect input format\n");
exit(EXIT_FAILURE);
}
read_ptr += n_read;
while (sscanf(read_ptr, "%lf %n", &c[i].measures[j], &n_read) == 1 &&
j < 15) {
read_ptr += n_read;
++j;
}
c[i].mnum = j;
++i;
j = 0;
read_ptr = buffer;
if (i == number_of_cities) {
break;
}
}
for (i = 0; i < number_of_cities; i++) {
printf("%s %d %d %d Number of measures: %zu\n",
c[i].name,
c[i].date.day, c[i].date.month, c[i].date.year,
c[i].mnum);
for (j = 0; j < c[i].mnum; j++) {
printf("%5g", c[i].measures[j]);
}
putchar('\n');
}
return 0;
}
Program output using your example data as input:
City0 28 2 2016 Number of measures: 10
1 2 3 4 5 6 7 8 9 10
City1 28 2 2016 Number of measures: 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
City2 1 3 2016 Number of measures: 5
1 2 3 4 5

Check if stdin pipe is empty in C

I am using user input to fill a 2d array. A user inputs numbers in one line and I then use nested loops to fill the array like so:
//User inputs: "1 2 3 4 5"
for(i = 0; i < r; i++){
for(j = 0; j < c; j++){
scanf("%d", &arr[i][j]);
}
}
However, the problem is if the user enters 5 ints when there is room for 6, it just waits for another input. How can I detect if there are insufficient numbers?
I have tried using this but it didn't work:
for(i = 0; i < r; i++){
for(j = 0; j < c; j++){
if (!feof(stdin)){
scanf("%d", &arr[i][j]);
}
else{
printf("insufficient datapoints\n");
}
}
}
One way to accomplish your goal would involve using fgets() instead of scanf() to read in a line of input at a time. Then strtok() can be used to break the line of input into tokens, and strtol() can be used to parse the tokens into numbers. Compared with scanf(), it is much easier to use fgets to handle unstructured user input.
The code below does this. If there are too many elements on an input row, too few elements, or if one of the elements is not a valid number, a message is printed and the row must be entered again.
As each line is entered by the user, strtok() is used to break the line into tokens. The list of token delimiters is stored in delims[]. Note that tokens may be separated by spaces or tabs; the delimiters themselves are not part of the token, so including \r and \n ensures that these characters will not be part of the final token in a line.
When a token is found, strtol() is used to convert it to an integer, if possible. After the call to strtol(), the pointer tail points to the first character in the token that was not part of a number; if tail points to the NUL terminator, then the entire string was parsed as a number, otherwise the input is considered bad and the row must be entered again.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 1000
int main(void)
{
size_t r = 3;
size_t c = 5;
size_t i, j;
char buffer[BUF_SIZE];
char *token;
char *tail;
const char delims[] = " \t\r\n";
int arr[r][c];
int temp_val;
printf("Enter rows of %zu data elements:\n", c);
for(i = 0; i < r; i++){
j = 0;
if (fgets(buffer, BUF_SIZE, stdin) == NULL) {
perror("Error in fgets()");
exit(EXIT_FAILURE);
}
token = strtok(buffer, delims);
while (token != NULL) {
temp_val = strtol(token, &tail, 10);
if (*tail == '\0') {
arr[i][j] = temp_val;
++j;
} else { // token not a valid number
j = 0;
break;
}
if (j > c) { // too many input values
break;
}
token = strtok(NULL, delims);
}
if (j != c) {
printf("insufficient datapoints\n");
--i; // enter row again
}
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
printf("%5d", arr[i][j]);
}
putchar('\n');
}
return 0;
}
Sample interaction:
Enter rows of 5 data elements:
1 2 3 4
insufficient datapoints
1 2 3 4 5 6
insufficient datapoints
1 x 2 3 4
insufficient datapoints
1 2 3 4 x
insufficient datapoints
1 2 3 4 5 x
insufficient datapoints
1 2x 3 4 5
insufficient datapoints
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
You can use peek ahead in the stream and test characters before you actually consume them. (Well sort of in c).
You can use this to ignore whitespace (you will need to do this).
You can also use this peeked value to indicate if insufficient characters have been input.
The peek needs to be done BEFORE the actual read (scanf).
Added rough example code below
#include <stdio.h>
#include <ctype.h>
int r=3;
int c=2;
int arr[100][100]; // FIX magic
int main(int argc, char** argv[]) {
for(int i=0; i<r; i++) {
for(int j=0; j<c; j++) {
if (feof(stdin)) {
// error check and error / normal exit etc.
printf("eof\n");
}
char c=getchar();
if (c=='\n') {
// error check and error / normal exit here
printf("newline\n");
} else if (isspace(c)) {
// advance and remove them - watch for end of stream when winding
printf("advance and discard whiitespace\n");
} else { // add check for isdigit
// push back
ungetc(c, stdin);
printf("ungetc\n");
}
scanf("%d", &arr[i][j]);
printf("got %d\n", arr[i][j]);
}
}
return 0;
}

Reading numbers from a text file into an array in C

I'm a programming noob so please bear with me.
I'm trying to read numbers from a text file into an array. The text file, "somenumbers.txt" simply holds 16 numbers as so "5623125698541159".
#include <stdio.h>
main()
{
FILE *myFile;
myFile = fopen("somenumbers.txt", "r");
//read file into array
int numberArray[16];
int i;
for (i = 0; i < 16; i++)
{
fscanf(myFile, "%d", &numberArray[i]);
}
for (i = 0; i < 16; i++)
{
printf("Number is: %d\n\n", numberArray[i]);
}
}
The program doesn't work. It compiles but outputs:
Number is: -104204697
Number is: 0
Number is: 4200704
Number is: 2686672
Number is: 2686728
Number is: 2686916
Number is: 2004716757
Number is: 1321049414
Number is: -2
Number is: 2004619618
Number is: 2004966340
Number is: 4200704
Number is: 2686868
Number is: 4200798
Number is: 4200704
Number is: 8727656
Process returned 20 (0x14) execution time : 0.118 s
Press any key to continue.
change to
fscanf(myFile, "%1d", &numberArray[i]);
5623125698541159 is treated as a single number (out of range of int on most architecture). You need to write numbers in your file as
5 6 2 3 1 2 5 6 9 8 5 4 1 1 5 9
for 16 numbers.
If your file has input
5,6,2,3,1,2,5,6,9,8,5,4,1,1,5,9
then change %d specifier in your fscanf to %d,.
fscanf(myFile, "%d,", &numberArray[i] );
Here is your full code after few modifications:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *myFile;
myFile = fopen("somenumbers.txt", "r");
//read file into array
int numberArray[16];
int i;
if (myFile == NULL){
printf("Error Reading File\n");
exit (0);
}
for (i = 0; i < 16; i++){
fscanf(myFile, "%d,", &numberArray[i] );
}
for (i = 0; i < 16; i++){
printf("Number is: %d\n\n", numberArray[i]);
}
fclose(myFile);
return 0;
}
for (i = 0; i < 16; i++)
{
fscanf(myFile, "%d", &numberArray[i]);
}
This is attempting to read the whole string, "5623125698541159" into &numArray[0]. You need spaces between the numbers:
5 6 2 3 ...
Loop with %c to read the stream character by character instead of %d.
There are two problems in your code:
the return value of scanf must be checked
the %d conversion does not take overflows into account (blindly applying *10 + newdigit for each consecutive numeric character)
The first value you got (-104204697) is equals to 5623125698541159 modulo 2^32; it is thus the result of an overflow (if int where 64 bits wide, no overflow would happen). The next values are uninitialized (garbage from the stack) and thus unpredictable.
The code you need could be (similar to the answer of BLUEPIXY above, with the illustration how to check the return value of scanf, the number of items successfully matched):
#include <stdio.h>
int main(int argc, char *argv[]) {
int i, j;
short unsigned digitArray[16];
i = 0;
while (
i != sizeof(digitArray) / sizeof(digitArray[0])
&& 1 == scanf("%1hu", digitArray + i)
) {
i++;
}
for (j = 0; j != i; j++) {
printf("%hu\n", digitArray[j]);
}
return 0;
}
enter your file input like this
ex:
12
13
22
45
(after every number hit enter)
then run your programm it will run properly

How to read a multi line using fscanf

I want to read my data.txt file which looks like and store it in an array called buffer[i][j]
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
I am writing a code which looks like
#include"stdio.h"
#include"stdlib.h"
int main() {
FILE *fp1;
int i,j;
int buffer[4][4]={0};
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
fscanf(fp1,"%d", &buffer[i][j]);
}
// fscanf(fp1,"\n");
}
fclose(fp1);
for(i=0;i<4;i++) {
for(j=0;j<4;j++) {
printf("%d ",buffer[i][j]);
}
printf("\n");
}
}
but i get the output...
1 1 2 1
5 1 6 1
17 1 18 1
21 1 22 1
why????
Always check the result of fopen() to ensure the file has been opened.
Always check the result of fscanf() to ensure it was successful and prevent subsequent code processing variables that may not have been assigned a value (it returns the number of assignments made).
Add a leading space character to the format specifier to skip whitespace, including newline characters: " %d".
The code will treat a single line with sixteen ints the same as four lines with four ints. If it is important that the format of the file is four ints per line then read a single line using fgets() and then use sscanf() to extract the ints with the %n format specifier to ensure full buffer was processed:
int ints[4][4] = { { 0 } };
char buffer[1024];
for (int i = 0; i < 4 && fgets(buffer, 1024, fp); i++)
{
int pos;
if (sscanf(buffer,
"%d %d %d %d%n",
&ints[i][0],
&ints[i][1],
&ints[i][2],
&ints[i][3],
&pos) != 4 || pos != strlen(buffer) - 1)
{
fprintf(stderr, "Invalid format: <%s>\n", buffer);
exit(1);
}
}
Add space at the beginning of the string format it should be " %d" to avoid the newline problems
fscanf(fp1," %d", &buffer[i][j]);
BTW you could use the following code instead
for(i=0;i<4;i++) {
fscanf(fp1," %d %d %d %d", &buffer[i][0], &buffer[i][1], &buffer[i][2], &buffer[i][3]);
}
To get required output (1111,2222,...) change:
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
to:
fp1 = fopen("data.txt","r");
Clarification: when using fopen you should write the name of file you want to read. In you case you have to write data.txt, not exact_enumerated_config_442_cub_mc...
There is no file with this name, moreover there is no any data like 1 1 1 1, 2 2 2 2, 3 3 3 3, 4 4 4 4...
For more detailes visit:
wikibooks.org/wiki/C_Programming/C_Reference/stdio.h/fopen
Here is your "modified" (excess/waste/extra { } removed and data.txt is written) code that gives you required output: 1 1 1 1, 2 2 2 2, 3 3 3 3, 4 4 4 4.
It prints the array named buffer. It means that...
...data was successfully copied! from "data.txt" to buffer[4][4]:
#include"stdio.h"
#include"stdlib.h"
int main()
{
FILE *fp1;
int i,j;
int buffer[4][4];
for ( i = 0; i < 4; i++ )
for ( j = 0; j < 4; j++ )
buffer[i][j] = 0;
fp1 = fopen("data.txt","r");
for(i=0; i<4; i++)
for(j=0; j<4; j++)
fscanf(fp1,"%d", &buffer[i][j]);
fclose(fp1);
for(i=0; i<4; i++)
{
for(j=0; j<4; j++)
printf("%d ",buffer[i][j]);
printf("\n");
}
return 0;
}
P.S.
If data.txt will contain not
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
but
1 1 1 1
2 2 2 2
3 3 3 3
4 444 // the last two elements are absent
the program will read 1-st, 2-nd and 3-rd line properly, and the output of the 4-th line will be
4 444 0 0
It prints 4, then 444, and then 0 and 0: the last two elements are '0's because buffer had been initialized by zeros, so all elements changed their values, but the last two remained to be zeros.
You have said you want to read data.txt then why are you opening the file exact_enumerated_config_442_cub_mc
Try changing this
fp1 = fopen("exact_enumerated_config_442_cub_mc","r");
to
fp1 = fopen("data.txt","r");

Resources