Populate a Matrix based on user input and a pattern in C - c

I have a program to develop but I'm having some difficulties in one part.
I have to read a number of tests (t) that will be made. After that I must read a number (n) of columns and rows to make a square matrix² (nxn). After instance of the matrix, the program must populate it from the input of the user. The user will type ., b or w. Based in this pattern I have to populate the matrix. Each line that the user will type must contain n characters (., b or w) and he will type n times. This will fill the matrix (n characters by n lines). Can you guys give me a hand?
This is the code I have:
int main(void)
{
//vars
int n = 0, t = 1, x = -1, y = -1, teste = 1;
int i,j;
//Start
scanf(" %d %*c",&t);//scans t
while (t-- > 0) {
scanf(" %d", &n);//scans n
if(n>0 && n < 100){
int table[n][n];//the matrix n x n
for (i = 0; (i < n);++i) {//iterator to lines
char l[n];
scanf ("%s", l); //scans a line
for (j = 0; j < n; ++j) {//iterator to colums
//these ifs are to identfy the input
if (l[j] == 'b'){
table[i][j]=1;
}else if(l[j] == 'w'){
table[i][j]=2;
x=j;y=i;
}else{
table[i][j]=0;
}
}
}
}
return 0;
}
I made the exactly same thing in Java and it worked. Where am I failing?

Your variable l doesn't allow enough space to store the null at the end of the string. You are therefore overflowing into some other variable, and that may be affecting all sorts of things.
You should probably read the line into a far larger string, and make sure it is the correct length. You should also error check each read operation; you should also report invalid characters in the input.
This code works for me. Note the way it echoes data so it is possible to see what's going wrong. Error reporting should really be to standard error; I've been lazy.
#include <stdio.h>
#include <string.h>
static void dump_board(FILE *fp, const char *tag, int n, int table[n][n])
{
fprintf(fp, "%s: (%d x %d)\n", tag, n, n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (table[i][j] == 0)
putc('=', fp);
else if (table[i][j] == 1)
putc('B', fp);
else if (table[i][j] == 2)
putc('W', fp);
else
putc('?', fp);
}
putc('\n', fp);
}
}
int main(void)
{
int n = 0, t = 1, x = -1, y = -1;
if (scanf(" %d %*c", &t) != 1)
{
printf("Failed to read t\n");
return 1;
}
printf("%d data sets\n", t);
while (t-- > 0)
{
if (scanf(" %d", &n) != 1)
{
printf("Failed to read n\n");
return 1;
}
printf("Size of data set: %d x %d\n", n, n);
int c;
while ((c = getchar()) != EOF && c != '\n')
;
if (n > 0 && n < 100)
{
int table[n][n];
for (int i = 0; i < n; i++)
{
char line[4096];
if (fgets(line, sizeof(line), stdin) == 0)
break;
int len = strlen(line);
if (line[len-1] != '\n')
{
printf("Format error: line too long (%d bytes)\n", len);
return 1;
}
line[--len] = '\0';
if (len != n)
{
printf("Format error: line <<%s>> is not length %d\n", line, n);
return 1;
}
for (int j = 0; j < n; ++j)
{
if (line[j] == 'b')
table[i][j] = 1;
else if (line[j] == 'w')
{
table[i][j] = 2;
x = j;
y = i;
}
else if (line[j] == '.')
table[i][j] = 0;
else
{
printf("Format error: invalid character %c\n", line[j]);
return 1;
}
}
}
dump_board(stdout, "Input", n, table);
printf("Last white piece at (%d,%d)\n", x, y);
}
}
return 0;
}
Input
2x
4
b..w
.bw.
.b.b
w.w.
8
b.w.b.w.
.w.b.w.b
bbwwbbww
b......w
ww....bb
bwb..wbw
bbbbwwww
........
Output
2 data sets
Size of data set: 4 x 4
Input: (4 x 4)
B==W
=BW=
=B=B
W=W=
Last white piece at (2,3)
Size of data set: 8 x 8
Input: (8 x 8)
B=W=B=W=
=W=B=W=B
BBWWBBWW
B======W
WW====BB
BWB==WBW
BBBBWWWW
========
Last white piece at (7,6)

Related

Problem with counting elements in the list of names

I have made one program, where you enter a few characters (10 max). It makes you a list, count average length of surnames, tell about how much different names. But the problem is, when I enter the last number (10) - it sorts me it incorrectly (like 1, 10, 2, 3, 4, 5, 6, 7, 8, 9). Beneath I will present my code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct people {
char num[2];
char surname[20];
char name[10];
} peoples[10], c;
int main()
{
int i, j, k = 0, l = 0, m = 0, n = 0;
float s = 0;
char str[100];
system("chcp 1251 > nul");
for (i = 0, j = 0; i < 10; i++, j++)
{
printf("Enter number, surname, name %d of your human: ", i + 1);
gets(str);
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].num[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].surname[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != '\0')
{
peoples[j].name[k] = str[n];
}
else
break;
n++;
k++;
}
n = 0;
k = 0;
}
for (i = 0; i < 10; i++)
{
for (j = i + 1; j < 10; j++)
{
if (!strcmp(peoples[i].name, peoples[j].name))
m = 1;
}
if (m == 0)
l++;
m = 0;
s = s + strlen(peoples[i].surname);
}
for (i = 0; i < 9; i++)
for (j = 0; j < 9; j++)
if (strcmp(peoples[j].num, peoples[j+1].num) > 0)
{
c = peoples[j+1];
peoples[j+1] = peoples[j];
peoples[j] = c;
}
for (i = 0; i < 10; i++)
{
printf("%s ", peoples[i].num);
printf("%s ", peoples[i].name);
printf("%s ", peoples[i].surname);
printf("\n");
}
printf("\nYou have %d different names\n", l);
printf("Avarege lenght of surname is = %f\n", s / 10);
}
If you want to give numeric input, then use actual numeric data.
Change the num field to become an int instead of a single-character string:
struct people {
int num;
char surname[20];
char name[10];
};
Use fgets to read the line:
fgets(str, sizeof str, stdin);
[Error checking left as exercise for reader]
Then use e.g. sscanf for parse your string:
sscanf(str, "%d %s %s", &peoples[j].num, &peoples[j].name, &peoples[j].name);
[Error checking left as exercise for reader]
And finally, instead of doing your own sorting use the standard qsort function:
qsort(peoples, 10, sizeof(struct people), &compare_people_num);
With the comparison function being something like this:
int compare_people_num(const void *a, const void *b)
{
const struct people *p1 = a;
const struct people *p2 = b:
return p1->num - p2->num; // Change order to reverse sort
}
Using sscanf and qsort will make your code much simpler and easier to understand.

garbage values while dynamic memory allocation

My code for dynamically allocating arrays, even though the Input methods for both arrays pattern and text are same text outputs different values, can anyone solve this issue?
#include<stdio.h>
#include<stdlib.h>
int main() {
int length=5;
int * pattern = malloc(length * sizeof(int));
int * text = malloc(length * sizeof(int));
int pattern_size=0;
int text_size=0;
printf("Enter Pattern:");
char c;
while(c != '$' && scanf("%c",&c) != '\n'){
if(pattern_size >= length)
pattern = realloc(pattern, (length += 10) * sizeof(int));
if(c!=',') pattern[pattern_size] = atoi(&c)+pattern[pattern_size]*10;
else if(c==',') {
pattern_size++;
}
}
printf("\nPlease enter the replacement text:");
// get_array(text,&text_size,length);
char d;
while(d != '$' && scanf("%c",&d) != '\n'){
if(text_size >= length)
text = realloc(text, (length += 10) * sizeof(int));
if(d!=',') text[text_size] = atoi(&d)+text[text_size]*10;
else if(d==',') {
text_size++;
}
}
for(int i=0;i<pattern_size; i++){
printf("%d ",pattern[i]);
}
printf("\n");
for(int i=0;i<text_size; i++){
printf("%d ",text[i]);
}
printf("\n");
return 0;
}
Input
Enter Pattern:1,2,3,4,5,6,7,8,9,0,$
Please enter the replacement text:1,2,3,4,5,6,7,8,9,0,$
OUTPUT
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 10417 8 540155953 540287027
You should ever check the return value of malloc and scanf.
Scanf does not return the element scanned. Please check man 3 scanf
On success, these functions return the number of input items
success‐ fully matched and assigned; this can be fewer than
provided for, or even zero, in the event of an early matching
failure. The value EOF is returned if the end of input is reached
before either the first successful conversion or a matching
failure occurs. EOF is also returned if a read error occurs, in
which case the error indicator for the stream (see ferror(3)) is
set, and errno is set to indicate the error.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main() {
int length = 1;
int *pattern = calloc(length, sizeof(int));
if (pattern == NULL) {
fprintf(stderr, "Unable to find free memory\n");
exit(EXIT_FAILURE);
}
int* text = calloc(length, sizeof(int));
if (text == NULL) {
fprintf(stderr, "Unable to find free memory\n");
exit(EXIT_FAILURE);
}
int pattern_size = 0;
int text_size = 0;
printf("Enter Pattern:\n");
char c = ' ';
while (c != '$') {
if (scanf("%c", &c) != 1) {
fprintf(stderr, "Error in scanf\n");
exit(EXIT_FAILURE);
}
if (isdigit(c) != 0) {
pattern[pattern_size] = c - 48;
pattern_size++;
pattern = realloc(pattern, (pattern_size + 1) * sizeof(int));
}
}
printf("\nPlease enter the replacement text:\n");
// get_array(text,&text_size,length);
char d = ' ';
while (d != '$') {
if (scanf("%c", &d) != 1) {
fprintf(stderr, "Error in scanf\n");
exit(EXIT_FAILURE);
}
if (isdigit(d) != 0) {
text[text_size] = d - 48;
text_size++;
text = realloc(text, (text_size + 1) * sizeof(int));
}
}
fprintf(stdout, "\nOUTPUT:\n");
for (int i = 0; i < pattern_size; i++)
printf("%d ", pattern[i]);
printf("\n");
for (int i = 0; i < text_size; i++)
printf("%d ", text[i]);
printf("\n");
return 0;
free(pattern);
free(text);
}
Including ctype.h you canuse the library function int isdigit(char c) that take in input a char and tells you if it is a number between 0 and 9.

C language - print the 3 most frequent characters from user input string [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
The goal of this program is to ask user for input and print the 3 most frequent characters from user's string. After few days I managed to make this kind of work. I mean kind of because if input will be "aaaaaaabbbbbccxz" program will work just fine, but if input will be "abc" program prints wrong values. Same with "aabbc", empty string, etc. I've been trying to fix that but with no luck. I have no idea what to do.
There's my code:
#include <stdio.h>
#include <stdlib.h>
#define N 100
/*
ask user to type letter string and load it to the array.
Count apperance of ASCII characters in the string
Print 3 most frequent characters from the string and how often they appeared.
*/
int main(int argc, char *argv[])
{
int ascii[256] = {0};
char str[N];
int z, i, j, k, top, top2, top3, index, index2, index3;
printf("Type your string: \n");
scanf("%s", &str);
for(i = 0; str[i] != 0; i++)
{
++ascii[str[i]];
}
top = ascii[0];
index = 0;
for(z = 0; str[z] != 0; z++)
{
if( ascii[str[z]] > top)
{
top = ascii[str[z]];
index = z;
}
}
printf("The most frequent is %c - was %d times.\n", str[index], top);
top2 = ascii[0];
index2 = 0;
for(j = 0; str[j] != 0; j++)
{
if( ascii[str[j]] > top2 && ascii[str[j]] < top)
{
top2 = ascii[str[j]];
index2 = j;
}
}
printf("second most frequent %c %d times.\n", str[index2], top2);
top3 = ascii[0];
index3 = 0;
for(k = 0; str[k] != 0; k++)
{
if( ascii[str[k]] > top3 && ascii[str[k]] < top2 && ascii[str[k]] < top)
{
top3 = ascii[str[k]];
index3 = k;
}
}
printf("3rd most frequent %c %d times.\n", str[index3], top3);
return 0;
}
EDIT:
it works.
#include <stdio.h>
#include <stdlib.h>
#define N 100
int main(int argc, char *argv[])
{
int ascii[256] = {0};
char str[N];
int x, y, z, i, j, k, top, top2, top3, index, index2, index3, len;
do
{
printf("String input here: \n");
fgets(str, N, stdin);
//scanf("%s", &str);
}
while (str[0] == '\n');
for(i = 0; str[i] != 0; i++)
{
++ascii[str[i]];
}
top = ascii[0];
len = strlen(str);
index = -1;
for(z = 0; str[z] != 0; z++)
{
if( ascii[str[z]] > top)
{
top = ascii[str[z]];
index = z;
}
}
if (index == -1) return printf("This string is empty\n");
else if (top == 1 && len > 1) return printf("There is no repeated character in that string\n");
else if (top == len) return printf("This string contains a single character '%c' - repeated %d times\n", str[index], top);
else {
// Checks the special case where several characters are repeated n times
char characters[len+1];
int count = 0;
for(i = 0; str[i] != 0; i++)
{
if (ascii[str[i]] == top && str[i] != characters[count-1])
characters[count++] = str[i];
}
characters[count] = 0;
if (count > 1) return printf("The most frequent characters are '%s' - repeated %d times.\n", characters, top);
else printf("The most frequent character is '%c' - repeated %d times.\n", str[index], top);
}
top2 = ascii[0];
index2 = -1;
for(j = 0; str[j] != 0; j++)
{
if( ascii[str[j]] > top2 && ascii[str[j]] < top)
{
top2 = ascii[str[j]];
index2 = j;
}
}
if (index2 == -1)
{
}
else if (top2 == 1 && len > 1)
{
}
else if (top2 == len)
{
}
else {
char characters[len+1];
int count = 0;
for(y = 0; str[y] != 0; y++)
{
if (ascii[str[y]] == top2 && ascii[str[y]] < top && str[y] != characters[count-1])
characters[count++] = str[y];
}
characters[count] = 0;
if (count > 1 )
{
}
else printf("The 2nd most frequent character is '%c' - repeated %d times.\n", str[index2], top2);
}
top3 = ascii[0];
index3 = -1;
for(k = 0; str[k] != 0; k++)
{
if( ascii[str[k]] > top3 && ascii[str[k]] < top2 && ascii[str[k]] < top)
{
top3 = ascii[str[k]];
index3 = k;
}
}
if (index3 == -1)
{
}
else if (top3 == 1 && len > 1)
{
}
else if (top3 == len)
{
}
else {
char characters[len+1];
int count = 0;
for(x = 0; str[x] != 0; x++)
{
if (ascii[str[x]] == top3 && ascii[str[x]] < top && ascii[str[x]] < top2 && str[y] != characters[count-1])
characters[count++] = str[x];
}
characters[count] = 0;
if (count > 1 )
{
}
else printf("The 3rd most frequent character is '%c' - repeated %d times.\n", str[index3], top3);
}
return 0;
}
You could do something like this and handle the second and third cases using a similar logic :
len = strlen(str);
index = -1;
for(z = 0; str[z] != 0; z++)
{
if( ascii[str[z]] > top)
{
top = ascii[str[z]];
index = z;
}
}
if (index == -1) return printf("This string is empty\n");
else if (top == 1 && len > 1) return printf("There is no repeated character in that string\n");
else if (top == len) return printf("This string contains a single character '%c' - repeated %d times\n", str[index], top);
else {
// Checks the special case where several characters are repeated n times
char characters[len+1];
memset(character, 0, len+1);
int count = 0;
for(i = 0; str[i] != 0; i++)
{
if (ascii[str[i]] == top && !strchr(characters, str[i]))
characters[count++] = str[i];
}
characters[count] = 0;
if (count > 1) return printf("The most frequent characters are '%s' - repeated %d times.\n", characters, top);
else printf("The most frequent character is '%c' - repeated %d times.\n", str[index], top);
}

I want to put some strings at dynamic 2D array with pointers(C programming)

Hi I want to get some strings from user then put those in 2D array and
at the end just print every character position in array for test.(Im writing at visual studio 2017)
but I'm getting output like this for example:
marray[1][2]==
marray[1][3]==
marray[1][3]==
and I'm getting this for all cells.
and here is my code so far:
#include <stdio.h>
#include <stdlib.h>
void inputnames(char**, int, int);
void printitems(char**, int, int);
int main(void)
{
int m;
const int n = 30; //students name limit
printf("Enter Number of students:");
scanf_s("%d ", &m); //getting row size from user
//---------------------------------------------
char** p;
p = (char**)malloc(sizeof(char)*m);
for (int i = 0; i < m; i++)
{ //this part for allocating 2d array
p[i] = (char*)malloc(sizeof(char)*n);
}
//--------------------------------------------
inputnames(p, m, n); //filling 2D array
printitems(p, m, n); //print each character with position for test
getchar();
}
void inputnames(char** marray, int mm, int nn)
{
int i = 0, j = 0;
for (i = 0; i<mm; i++)
{
while (marray[i][j] != '\n' && j<nn)
{
scanf_s("%c", &marray[i][j]);
}
}//end of for i
}
void printitems(char** marray, int mm, int nn) //this function is for test
{
int i = 0, j = 0;
for (i = 0; i<mm; i++)
{
for (j = 0; j<nn; j++)
{
printf("marray[%d][%d]=%c\n",i,j,marray[i][j]);
}//end of for j
}//end of for i
}
There are several error in your code.
Don't cast malloc. And your are allocating the incorrect number of bytes
both times. I advice you not to use sizeof(<type>), it's easy to make
mistakes, it's better practice to call malloc like this:
int *arr = malloc(size * sizeof *arr);
Regardless of the type of arr, you would allocate the correct amount of
memory.
You have to check if malloc returns NULL. If it returns NULL you cannot
access the memory.
Also remember that a string must be '\0'-terminated, for a string of length
n, you need n+1 bytes. You either allocate n+1 spaces for the strings, or
in inputnames you should check if j < nn - 1. Also you don't set the
'\0'-terminating byte in inputnames.
The correct allocation is:
char** p;
// calloc initializes the memory to 0,
// great initialization, helps you free the memory faster
// on error
p = calloc(m, sizeof *p);
if(p == NULL)
{
fprintf(stderr, "not enough memory\n");
return 1;
}
for (size_t i = 0; i < m; i++)
{
p[i] = calloc(1, n+1); // size of char is 1
if(p[i] == NULL)
{
fprintf(stderr, "not enough memory\n");
free_strings(p, m);
return 1;
}
}
And you would need the free_strings function:
void free_strings(char **strings, size_t len)
{
if(strings == NULL)
return;
for(size_t i = 0; i < len; ++i)
free(strings[i]);
free(strings);
}
Also your reading is not that efficient, I would use fgets instead:
int inputnames(char** marray, size_t mm, size_t nn)
{
if(marray == NULL || mm == 0 || nn == 0)
return 0;
for(size_t i = 0; i < mm; ++i)
{
printf("Enter text #%d: ", i+1);
fflush(stdout);
if(fgets(marray[i], nn, stdin) == NULL)
{
fprintf(stderr, "cannot read anymore\n");
return 0;
}
// removing the newline
marray[i][strcspn(marray[i], "\n")] = 0;
}
return 1;
}
I forgot to mention this in the answer:
for (i = 0; i<mm; i++)
{
while (marray[i][j] != '\n' && j<nn)
{
scanf_s("%c", &marray[i][j]);
}
}//end of for i
This yields undefined behaviour. You only allocate memory but you don't
initialize it, so you are actually checking if random value if equals to the
newline. You also don't increment j, you are writing always at the same place.
You need to read first, then check second.
for(i = 0; i<mm; i++)
{
do {
if(scanf_s("%c", marray[i] + j) != 1)
{
fprintf(stderr, "Unable to read from stdin\n");
marray[i][j] = 0;
return;
}
} while(marray[i][j++] != '\n' && j<nn);
marray[i][j-1] = 0; // setting the \0-terminating byte
}
and the printitems should look like this:
void printitems(char** marray, size_t mm)
{
if(marray == NULL || mm == 0 || nn == 0)
return;
for(size_t i = 0; i < mm; ++i)
puts(marray[i]);
}
Also don't forget to free the memory when you don't need it anymore.

how to get space seperate array value and store it in an array? example: input in form 10 20 30 ouput:a[0]=10 a[2]=20 a[3]=30

how to get space seperated integer value in single line and store it in array variable:
input:
10 20 30
how can i store it in
a[0],a[1],a[3]
My code
#include<stdio.h>
#include<conio.h>
int main()
{
int i = 0, j, arr[100], n, x;
while(i < 100 && scanf("%d", &arr[i]) == 1)
{
i++;
}
for(j = 0; j < i; j++)
{
printf("%d\n", arr[j]);
}
return 0;
}
I assume that your problem is that your program doesn't carry on after input like:
10 20 30
The reason is that the program gets stuck in the scanf waiting for more input.
You can make the program carry on by input like:
10 20 30 x
but that is probably not what you want.
Instead you can read a whole line using fgets and the parse the line.
Something like:
#include<stdio.h>
#include<string.h>
int main()
{
char line[1000];
int i = 0, j, arr[100];
fgets(line, 1000, stdin);
char* p = line;
while(i < 100 && sscanf(p, "%d", &arr[i]) == 1)
{
i++;
// Remove leading spaces
while(*p == ' ') ++p;
// Advance to next space
p = strchr(p, ' ');
if (p == NULL)
{
// All input handled
break;
}
}
for(j = 0; j < i; j++)
{
printf("%d\n", arr[j]);
}
return 0;
}
I checked your code and the reading part actually works. I assume, however, your problem is getting out of the reading loop...
Try with a smaller array (let's say of size 3) and input numbers accordingly and you'll see; other variant: leave your big array, input three numbers and then xyz (which can't be evaluated by your scanf expression).
Problem is that if you press enter, scanf simply reads a new-line character, which is considered as any other whitespace, so scanf expects further input (try again with array of size 3 and enter three numbers, each being terminated by pressing enter and you'll see).
So you would have to scan for new line character explicitly, but that gets ugly quickly. You're better of by reading one line at once and then scan the input buffer using sscanf:
char buffer[256];
fgets(buffer, sizeof(buffer), stdin);
int i = 0, j, arr[100];
char* b = buffer;
int n = 0;
while(i < 100 && sscanf(b, "%d%n", &arr[i], &n) == 1)
{
b += n;
i++;
}
for(j = 0; j < i; j++)
{
printf("%d\n", arr[j]);
}
A variant without the line buffer could look like this:
int i = 0, j, arr[3];
while(i < 3 && scanf("%d", &arr[i]) == 1)
{
char c;
do
{
scanf("%c", &c);
}
while(isspace(c) && c != '\n');
++i;
if(c == '\n')
break;
ungetc(c, stdin);
}
for(j = 0; j < i; j++)
{
printf("%d\n", arr[j]);
}

Resources