taking a matrix input from the user in c - c

I would like to taking a 5x5 matrix input from the user with scanf in c.
for example, if the user type 1 2 3 4 5 6 7 8 9 10, i want to create a 2d array like this: arr[0][0] = 1 , ... arr[1][0]=6 .. etc
the input also can be with new line.
I tried this:
int main() {
int arr[5][5]; eipus(arr);
char c; int r=0; int col=0;
while ((c=getchar()) != EOF) {
if (col >= 5) { col=0; r++; }
if (scanf("%d",&arr[r][col]) == 1) { col++; }
}
printArr(arr);
return 1;
}
eipus() - set the array to 0. printArr - print the array.
the problem is that it always ignores the first number. for example:
[admin#server]$ a.out
1 2 3 4 5 6 7 8
2 3 4 5 6
7 8 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
number 1 ignored. but if there is a space before 1, it's ok.

getchar() consumes one character. For more interesting result try giving input
12 3 4
You will get the first element to be 2 then.
Use ungetc() to get back the previous state before reading it.
while ((c=getchar()) != EOF) {
ungetc(c,stdin);
if (col >= 5) { col=0; r++; }
if (scanf("%d",&arr[r][col]) == 1) { col++; }
}
By the way you need to make it int c as EOF is nothing but -1

The very first character you enter gets scanned in variable c due to the line
while ((c=getchar()) != EOF) .
You can enter the value scanned c in the matrix elements throughout the loop.

Related

I cannot understand core dump cause of fgetc, how can I fix it?

I allocated matrix like this :
prevMatrix = (int**)malloc(sizeof(int) * arraySize[0]);
for (int i = 0; i < arraySize[0]; i++) {
prevMatrix[i] = (int*)malloc(sizeof(int) * arraySize[1]);
}
I checked arraySize[] has normal value. arraySize[0] means row, and arraySize[1] means column.
and I handed over the matrix like this :
void getInputMatrix(FILE* input, int column, int** matrix)
getInputMatrix(input, arraySize[1], prevMatrix);
and then function's body is this :
void getInputMatrix(FILE* input, int column, int** matrix) {
int i = 0, j = 0, c = 0;
while (!feof(input)) {
if (j == column) {
j = 0;
i++;
}
c = fgetc(input);
if (c != EOF && c != 32 && c != 10 && c != 13) {
matrix[i][j] = c - 48;
j++;
}
}
}
this is the example of matrix file:
1 0 0 0 0 0 0
0 1 0 1 0 0 0
0 1 0 0 1 1 0
0 1 1 1 0 0 0
0 0 0 0 1 0 0
0 1 0 0 0 1 0
1 0 1 1 0 0 0
0 1 0 0 0 0 1
It works very well in VS 2019, but it cause segmentation fault in Linux system(Ubuntu).
This program works well in Linux till the column is 6 or 7, but it occurs corrupted size vs. prev_size error or segmentation faultwhen the column overs that number.
Is it a problem of allocation? or fgetc()?
How can I fix it?
For starters, your first level allocation should be using the size of an int pointer rather than an int:
int **prevMatrix = malloc(sizeof(int*) * arraySize[0]);
If those types are different sizes, your original code could have a problem.
And, just as an aside, you should not cast the malloc return value in C, it can cause subtle problems.

How to read a file, convert letters, and print string and integers to an array in c?

struct reviewStruct {
char reviewer[50];
int feedback[3];
};
int readReviews(FILE *file, struct reviewStruct reviews[10]) {
int i;
file = fopen("Names.txt", "r");
if(file == NULL) {
printf("Error");
exit(-1);
}
for(i = 0; i < 10; i++) {
fgets(reviews[i].reviewer, 50, file);
}
fclose(file);
for(i = 0; i < 10; i++) {
printf("%s", reviews[i].reviewer);
}
return 0;
}
Hello, I'm trying to read a file line by line and print it to an array, with a catch. Whenever a 'Y' or 'y' appears, it converts that letter into a 1, and if an 'N' or 'n' appears, it is converted into a 0 (zero), excluding the first word of every line. For example, I have a file with the following information:
charlie Y n N
priya N n Y
lance y y Y
stan N y n
arin N n N
This is the text file called Names.txt, I want to save the integer information to the array called "feedback", so that it looks like this when printed using a for loop:
1 0 0
0 0 1
1 1 1
0 1 0
0 0 0
How do I populate the feedback array such that it can be printed along with the names using a for loop as it is in the following image?
charlie 1 0 0
priya 0 0 1
lance 1 1 1
stan 0 1 0
arin 0 0 0
Thanks.

How to get the third column of text file in C programming

I have a text file that contains:
1 1 1
1 2 2
1 3 2
1 7 5
1 8 4
1 9 4
1 10 2
...
and this is my function:
void addRatings()
{
int n,m,l;
int a[50][100];
MovieR = fopen("d://ratings.txt","r");
l = LineNum(MovieR);
MovieR = fopen("d://ratings.txt","r");
for(int i=0;i<l;i++)
{
fscanf(MovieR,"%[^\t]\t%[^\t]\t%[^\t]\n",&n,&m,&a[n][m]);
}
}
Now I want to get the first and second column for n and m
then I want to give third column to the a[n][m].
How can I do that?
You need to read the third value into a temporary variable, and then store that value into the array if and only if the following conditions are met:
fscanf returned 3, meaning that it actually found three numbers
the value for n is between 0 and 49 inclusive
the value for m is between 0 and 99 inclusive
And the code doesn't need to count the number of lines (using LineNum()). The loop should end when fscanf runs out of numbers to read, i.e. returns something other than 3.
The resulting code looks something like this:
void addRatings(void)
{
int a[50][100] = {{0}}; // initialize all ratings to 0
FILE *MovieR = fopen("d://ratings.txt", "r");
if (MovieR != NULL)
{
int n, m, rating;
while (fscanf(MovieR, "%d%d%d", &n, &m, &rating) == 3) // loop until end-of-file
{
if (n < 0 || n > 49 || m < 0 || m > 99) // check for valid indexes
break;
a[n][m] = rating;
}
fclose(MovieR);
}
}

logical multiplication of matrices A and B by the operation "AND" and "OR" in C

This is the question:
A logical matrix is a matrix in which all its elements are either 0 or
1.
We define logical multiplication of matrices A and B by the operation
defined below, where "·" is the logical AND operation, and "+" is the
logical OR operation.
In this assignment, you will create two 5x5 logical matrices and find
the corresponding matrix which will be created from "multiply" these 2
matrices
Define global SIZE equals to 5 (Already defined in the template)
Write a function that gets a matrix reference and reads the input
to the matrix from the user. If the input is non-zero replace it by 1.
If the user did not enter enough values before the end of the line,
the remaining cells in the matrix will be populated with zeros. Also
make sure if the user inputs too many characters, you only take what's
needed and discard the remaining input. (Eg: 1509 is a 2x2 matrix with
values 1101, and ‘1 5 ‘ is also a 2x2 matrix with values 1111, the
highlighted whitespace is taken as a 1 as discussed above.)
Function signature: void read_mat(int mat[][SIZE])
Write a function that multiplies, as defined above, two matrices
and enters the results into a third matrix with suitable dimensions.
Function signature: void mult_mat(int mat1[][SIZE],int mat2[][SIZE], int result_mat[][SIZE])
Write a function that prints a matrix into the screen. Please use
“%3d” for printing format to make it look nice as shown below.
Function signature: void print_mat(int mat[][SIZE])
Write the main program which uses the functions above. The program
reads the matrices values from the user, multiplies them and prints
the result matrix on the screen.
The function definitions given are intentional with the return
statements as void. Do not change them. Arrays are transferred between
functions as references rather as primitives like variables. So the
function definitions are perfectly valid. Also, there is no limit on
the input from the user. You can read only the required digits, and
then stop reading, and discard the remaining input.
Here is my code:
#include <stdio.h>
#define SIZE 5
void read_mat(int mat[][SIZE],int size)
{
int i = 0, j = 0, k = 0;
char c;
c=getchar();
while(c!='\n' && k<size*size){
if(c!='0'){
mat[i][j]=1;
j++;
}
else{
mat[i][j]=0;
j++;
}
if (j >= size){
j = 0;
i++;
}
if (i >= size){
return;
}
c=getchar();
k++;
}
}
void mult_mat(int mat1[][SIZE], int mat2[][SIZE], int result_mat[][SIZE])
{
int i,j,k;
for (i = 0; i <SIZE; ++i){
for (j = 0; j <SIZE; ++j)
{
result_mat[i][j] = 0;
for (k = 0; k < SIZE; ++k)
result_mat[i][j] += mat1[i][k] * mat2[k][j];
if(result_mat[i][j]!=0){
result_mat[i][j]=1;
}
}
}
}
void print_mat(int mat[][SIZE],int size)
{
int i, j;
for (i = 0; i < SIZE; i++) {
for (j = 0; j < SIZE; j++)
printf("%3d", mat[i][j]);
printf("\n");
}
//Please use the "%3d" format to print for uniformity.
}
int main()
{
int mat1[][SIZE]={ 0 }, mat2[][SIZE]={ 0 }, res_mat[][SIZE]={0};
printf("Please Enter Values For Matrix 1\n");
read_mat(mat1,SIZE);
printf("Please Enter Values For Matrix 2\n");
read_mat(mat2,SIZE);
mult_mat(mat1,mat2,res_mat);
printf("The First Matrix Is :- \n");
print_mat(mat1,SIZE);
printf("The Second Matrix Is :- \n");
print_mat(mat2,SIZE);
printf("The Resultant Matrix Is :- \n");
print_mat(res_mat,SIZE);
return 0;
}
The input and output should be like this:
Please Enter Values For Matrix 1
111000654987010
Please Enter Values For Matrix 2
11 53
The First Matrix Is :-
1 1 1 0 0
0 1 1 1 1
1 1 0 1 0
0 0 0 0 0
0 0 0 0 0
The Second Matrix Is :-
1 1 1 1 1
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
The Resultant Matrix Is :-
1 1 1 1 1
1 0 0 0 0
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
But when I run the program, this message appears:
exception thrown: Run-Time Check Failure #2 - Stack around the variable 'mat2' was corrupted.
and the output isn't right and I am getting some elements has a junk values:
Please Enter Values For Matrix 1
111000654987010
Please Enter Values For Matrix 2
11 53
The First Matrix Is :-
1 1 1 0 0
0 1 1 1 1
1 1 1 1 1
1 1-858993460-858993460-858993460
-858993460-858993460-858993460-858993460 1
The Second Matrix Is :-
1 1 1 1 1
-858993460-858993460-858993460-858993460-858993460
-858993460-858993460 1 1 1
1 1 1 1 1
1 1 1 1 1
The Resultant Matrix Is :-
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
Another question:
if I entered to the mat1 a big string it's calculated directly without letting me enter a string to mat2 how do I solve this problem ?
int mat1[][SIZE]={ 0 }
will declare a 1x5 matrix. Change it to
int mat1[SIZE][SIZE]={ 0 }

Debugging a histogram in C

First question here on Stack Overflow so forgive me if this is offtopic or not per etiquette, but it seems like it should be fine. I'm doing exercise 1-13 in K&R, specifically printing a vertical histogram of the length of words in an input. Here's my code so far:
#include <stdio.h>
#define UPPER 10
#define ABOVE (UPPER+1)
main()
{
int i, c, wcounter, j;
int wlengths[ABOVE];
int maxHistHeight;
for (i = 0; i <= ABOVE; ++i) /* Initialize everything to zero */
wlengths[i] = 0;
wcounter = maxHistHeight = 0;
while((c = getchar()) != EOF){ /* Count word lengths */
if (c != ' ' && c != '\t' && c != '\n'){
++wcounter;
}
else if (wcounter >= ABOVE){
++wlengths[ABOVE];
wcounter = 0;
}else if (wcounter != 0){
++wlengths[wcounter];
wcounter = 0;
}
}
for (i = 1; i <= ABOVE; ++i) /*For testing purposes. See if the array is holding correct values*/
printf(" %d ",wlengths[i]);
printf("\n");
for (i = 1; i <= ABOVE; ++i) /*Get the Maximum height for histogram */
if (wlengths[i]>maxHistHeight)
maxHistHeight = wlengths[i];
printf("Histogram of length of words\n"); /* Print histogram */
printf("----------------------------\n");
for (i = maxHistHeight; i >= 0; --i){ /* Start at top of histogram, and go downwards */
printf("\n");
for (j = 1; j <= ABOVE; ++j){ /*For each level of histogram, go through all the */
if (i == 0 && j != ABOVE){ /*Arrays, and see if they contain an X in that level */
printf(" %d ", j);
}else if (i == 0 && j == ABOVE){
printf(">%d",UPPER);
}
else if (wlengths[j]>=i){
printf(" X ");
}
else{
printf(" ");
}
}
}
printf("\n");
}
I want to print a histogram of the length of words that are 1-10 letters long, and also that are greater than 10 letters. I want it to look like this:
Histogram of length of words
X
X X X
1 2 3 4 5 6 7 8 9 10 >10
I'm using an array that is size 12 (not sure if this is how you would say it), with the 11th index holding all occurrences of words greater than 10 letters long. However, when I print out the histogram, it prints out an "X" in the >10 spot even if the word is only 10 letters long. So if I input this:
1234567890
123457890
1234567890
I get:
Histogram of length of words
----------------------------
X X
X X X
1 2 3 4 5 6 7 8 9 10 >10
I thought there must've been something with wrong with the way I was incrementing my array, so I printed the values of the array and got this:
0 0 0 0 0 0 0 0 1 2 0
which doesn't match what my histogram is printing. I appreciate any help!
UPDATE TO ORIGINAL QUESTION
So I fixed my array size to hold 12 elements: 10 for holding words with length 1-10, 1 for all words with length >10, and 1 for index 0, so that my index numbers match up with my word lengths. Before I had an array with just 11 elements,when I needed it to be 12, but when i printed out the values of my array, it displayed the correct values but during the printing of the histogram, it was incorrect. so given an input of this:
1234567890
1234567890
12345678901234567890
12345
I got this in the array (i'm printing from index 1 to index 11), and its correct:
0 0 0 0 1 0 0 0 0 2 1
But the histogram printout is different:
Histogram of length of words
----------------------------
X X
X X X
1 2 3 4 5 6 7 8 9 10 >10
Shouldn't they both be the same?
You array has dimension ABOVE (= 11) but you're iterating from 0 to ABOVE (inclusive) which is ABOVE + 1 (= 12) elements. The valid index range is only 0 to ABOVE - 1 so you're writing (and subsequently reading) beyond the end of the allocated array.
E.g. your initialisation loop should be:
for (i = 0; i < ABOVE; ++i) /* Initialize everything to zero */
wlengths[i] = 0;
I think you're probably getting muddled because C array indexes start at 0, while your histogram needs to represent word lengths from 1 to 10 and then 11 for word lengths > 10. You can approach this in one of two ways, either:
(a) adjust for the difference of 1, so words of length 1 go in bin 1, words of length 2 go in bin 1, etc, or
(b) allocate an additional element (i.e. make the array one element bigger than it needs to be) and simply don't use element 0. That way you don't have to worry about the offset of 1.
Lengths:
If you declare an array as
things[LEN]
then the array can hold LEN things.
Indexes:
But the array elements are indexed from
0 through LEN-1
and are accessed as
things[0], things[1], ..., things[LEN - 1]
So you'll commonly see loops looking like this:
for (i = 0; i < LEN; i++) {
do something with thing[i];
}
The problem is that you want word lengths from 1 to 10, so you need to
adjust the array indices accordingly.
Okay, I think I see what you guys meant. My array needs to be able to store 12 elements, assuming that I use indices 1-10 for word lengths 1-10, index 11 for all those word lengths >10, and finally, index 0 is discarded because I want the index numbers to line up with my word lengths. I set my array size to 12, or 2 more than my UPPER constant, and that seems to have done the trick. Here's my output:
Histogram of length of words
----------------------------
X
X X X
1 2 3 4 5 6 7 8 9 10 >10
given this input:
1234567890
1234567890
12345
12345678901234567890

Resources