The problem is the following:
Have to check if the words in the matrix are palindromes or not. Have to read the words as well.
My main problem is introducing the words because until now I could only do a function reading the first letter, not the whole word.
After that, I think that I can check alone if it is a palindrome or not.
This is an example of data:
mat←["ac" "lup" ]
["ou" "lupul"]
["ABBA" "greu" ]
m←3 number of rows
n←2 number of columns
This what I wrote until now:
A function where you introduce the words:
char** read(int *m ,int *n)
{
printf("No of lines=");
scanf("%d",m);
printf("No of columns=");
scanf("%d",n);
char **a=(char**)malloc(*m*sizeof(char*));
for (int i=0;i<*m;i++)
{
a[i]=(char*)malloc(*n*sizeof(char));
for (int j=0; j<*n; j++)
{
fflush(stdin);
printf("Element [%d][%d]=",i,j);
gets(a[i]+j); // <=> &a[i][j]
}
}
return a;
}
Another one which displays it:
void display(char **x, int m, int n)
{
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
printf("%c ",x[i][j]);
printf("\n");
}
}
Another one which deletes the data:
void freematrix(char **x, int m)
{
for (int i=0; i<m; i++)
free(x[i]);
free(x);
}
This is the main part:
int main()
{
int m, n;
char **mat;
mat=read(&m,&n);
display(mat,m,n);
freematrix(mat,m);
return 0;
}
Try this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_ROWS 8 // to limit the usecase
#define MAX_COLS 8
#define MAX_MAT_STR_LEN 15 //
char* str_dupe (const char* str, const int max_slen)
{
if (!str || max_slen < 1) return NULL;
char* dupe = malloc (max_slen + 1);
if (!dupe) {
perror("\nERROR: str_dupe-malloc");
return NULL;
}
dupe[max_slen] = '\0'; // guard
for (int ci =0; ci < max_slen; ++ci) {
dupe[ci] = str[ci];
if ('\0' == dupe[ci])
break; // stop copying
}
return dupe;
}
void free_strMatrix (char ***sm, const int rows, const int cols)
{
if (!sm || rows < 1 || cols < 1) return;
for (int ri = 0; ri < rows; ++ri) {
if (sm[ri]) {
for (int ci = 0; ci < cols; ++ci) {
if (sm[ri][ci]) { // check if it's NULL
free (sm[ri][ci]);
sm[ri][ci] = NULL; //prevent dangling pointers
}
}
free (sm[ri]); // row of string pointers
sm[ri] = NULL; // good practice
}
}
free (sm);
}
char*** read_strMatrix (int *rows, int *cols)
{
while (1) {
printf ("\nChoose Rows [1..%d]: ", MAX_ROWS);
if (1 == scanf("%d", rows) && *rows > 0 && *rows <= MAX_ROWS)
break;
else
printf ("\nERROR: Invalid Row-Count. Try Again!");
}
while (1) {
printf ("\nChoose Columns [1..%d]: ", MAX_COLS);
if (1 == scanf("%d", cols) && *cols > 0 && *cols <= MAX_COLS)
break;
else
printf ("\nERROR: Invalid Column-Count. Try Again!");
}
char*** sm = (char***) calloc ((*rows), sizeof (char**));
if (NULL == sm) {
perror("read_strMatrix-malloc-1");
return NULL;
}
for (int ri = 0; ri < *rows; ++ri) {
sm[ri] = (char**) calloc ((*cols), sizeof (char*));
if (NULL == sm[ri]) {
perror ("read_strMatrix-malloc-2");
//ideally you should free allocated memory before return
free_strMatrix(sm, *rows, *cols);
return NULL;
}
}
char str[256]; //interim string buffer;
for (int ri = 0; ri < *rows; ++ri) {
for (int ci=0; ci < *cols; ++ci ) {
printf ("String for strMatrix[%d][%d] : ", ri, ci);
// strings more than 255 chars will be split ; so be within limit duing input
while (1 != scanf ("%255s", str));
// only copying MAX_MAT_STR_LEN chars
sm[ri][ci] = str_dupe (str, MAX_MAT_STR_LEN);
if (NULL == sm[ri][ci]) {
perror("read_strMatrix-strndup");
//ideally you should free allocated memory before return
free_strMatrix (sm, *rows, *cols);
return NULL;
}
}
printf ("\n");
}
return sm;
}
void disp_strMatrix (char ***sm, const int rows, const int cols)
{
if (!sm || rows < 1 || cols < 1) return;
printf ("\nStringMatrix [%d][%d]:\n", rows, cols);
for (int ri = 0; ri < rows; ++ri) {
if (sm[ri]) {
for (int ci = 0; ci < cols; ++ci)
printf ("%s\t", sm[ri][ci]);
}
printf ("\n");
}
printf ("\n");
}
int main()
{
int rows, cols;
char ***strMatrix;
strMatrix = read_strMatrix (&rows, &cols);
if (!strMatrix) {
printf ("\nERROR: reading strMatrix\n");
return 1;
}
disp_strMatrix (strMatrix, rows, cols);
free_strMatrix (strMatrix, rows, cols);
strMatrix = NULL; // good practice
return 0;
}
You can also prepare an input.txt file like:
3 4
aaaaa sssss ffg gggg
hhhh jj kkkkkk lllll
qqq wwwww eeeee rrrrr
On Linux you can run the program like:
./a.out < input.txt
Related
I'm trying to make a columnar transposition in C. The user inputs a string and key. The length of the key determines how many columns there are.To encryp the message the key must be sorted alphabetically. Here is an example using the string as hello there and the key as 'KEY'.
I created a function to sort the key alphabetically but I have no clue how to swap the columns.
void gridStr(char *line, char *key);
char encrypt(char *key);
int main(void) {
char key[50];
char line[256];
printf("Enter your string: ");
if (fgets(line, sizeof line, stdin) == NULL) {
fprintf(stderr, "No line read\n");
exit(EXIT_FAILURE);
}
printf("Enter your key: ");
if (fgets(key, sizeof key, stdin) == NULL) {
fprintf(stderr, "No line read\n");
exit(EXIT_FAILURE);
}
int len = strlen(line);
if (len && line[len - 1] == '\n')
line[--len] = '\0';
int len1 = strlen(key);
if (len1 && key[len1 - 1] == '\n')
key[--len]= '\0';
gridStr(line, key);
encrypt(key);
}
void gridStr(char *line, char *key)
{
char mat[10][10] = {0};
int columns = strlen(key)-1;
int rows = 0;
int i=0,j = 0;
while (line[i]) {
if (line[i] == ' ') {
putchar('_');
} else {
putchar(line[i]);
}
mat[rows][i % columns] = line[i];
i++;
if (i > 0 && i % columns == 0) {
putchar('\n');
rows++;
}
}
if (i % columns != 0) putchar('\n');
rows++; // from current row to number of rows
printf("\nMatrix:\n");
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
if (mat[i][j] == ' ') {
putchar('_');
} else {
putchar(mat[i][j]);
}
}
printf("\n");
}
}
char encrypt(char *key){
char temp;
int i,j;
int n = strlen(key);
for (i = 0; i < n-1; i++) {
for (j = i+1; j < n; j++) {
if (key[i] > key[j]) {
temp = key[i];
key[i] = key[j];
key[j] = temp;
}
}
}
printf("The sorted string is : %s", key);
return 0;
}
You do not want to swap the columns each time a bubble moves in the sorting algorithm until it reaches its final position. Therefore, the sorting can be performed separately.
Determining which columns to swap is implemented in the following way:
Iterate over all columns from start to end
If a column has not been swapped, find its counterpart and swap them
Mark both swapped columns in order to not swap them again, continue iteration
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
// use bubble sort to sort letters in a string
void sort_letters(char *phrase) {
int n = strlen(phrase);
//printf("The string to sort is: %s\n", phrase);
for (int i = 0; i < n-1; i++) {
for (int j = i+1; j < n; j++) {
if (phrase[i] > phrase[j]) {
char temp = phrase[i];
phrase[i] = phrase[j];
phrase[j] = temp;
}
}
}
//printf("The sorted string is: %s\n", phrase);
}
// allocate a matrix for string and fill it
char** gridStr(char *line, char *key)
{
int n = strlen(line);
int columns = strlen(key);
int rows = (n + columns - 1) / columns;
char **matrix = malloc(rows * sizeof(char *));
for (int j = 0; j < rows; j++) {
matrix[j] = malloc(columns * sizeof(char));
}
int i = 0;
for (int k = 0; k < rows; k++) {
for (int l = 0; l < columns; l++) {
if (i<n) {
matrix[k][l] = line[i++];
} else {
matrix[k][l] = '*'; // fill letter
}
//putchar(matrix[k][l]);
}
//putchar('\n');
}
return matrix;
}
// swap columns i and j of the given matrix, zero-based indices
void swap_matrix_columns(char **matrix, int rows, int columns, int i, int j) {
for (int k = 0; k < rows; k++) {
char tmp = matrix[k][i];
matrix[k][i] = matrix[k][j];
matrix[k][j] = tmp;
}
}
// print matrix to stdout
void print_matrix(char **matrix, int rows, int columns) {
for (int i = 0; i < rows; i++){
printf("Row %2d: ", i);
for (int j = 0; j < columns; j++) {
putchar(matrix[i][j]);
}
putchar('\n');
}
}
// sort key and transpose matrox columns according new order
void encrypt(char **matrix, int rows, int columns, char *key) {
char sorted_key[strlen(key)];
strcpy(sorted_key, key);
sort_letters(sorted_key);
printf("Sorted key: %s (length: %2zu)\n", sorted_key, strlen(sorted_key));
bool is_used[columns];
for (int i = 0; i < columns; i++) is_used[i]= false;
for (int i = 0; i < columns; i++) {
if (!is_used[i]) {
// find new position, must exist
int j;
for (j = 0; j < columns; j++) {
if (key[i] == sorted_key[j] && !is_used[j]) {
break;
}
}
swap_matrix_columns(matrix, rows, columns, i, j);
is_used[i] = true;
is_used[j] = true;
}
}
}
int main(void) {
char key[50];
char line[256];
printf("Enter your string: ");
if (fgets(line, sizeof line, stdin) == NULL) {
fprintf(stderr, "No line read\n");
exit(EXIT_FAILURE);
}
printf("Enter your key: ");
if (fgets(key, sizeof key, stdin) == NULL) {
fprintf(stderr, "No line read\n");
exit(EXIT_FAILURE);
}
int len = strlen(line);
if (len && line[len - 1] == '\n') {
line[--len] = '\0';
}
int len1 = strlen(key);
if (len1 && key[len1 - 1] == '\n') {
key[--len1]= '\0';
}
//printf("string: |%s| (length: %2zu)\n", line, strlen(line));
//printf("key: |%s| (length: %2zu)\n", key, strlen(key));
char **matrix = gridStr(line, key);
int columns = len1;
// Use simple trick (+ len1 - 1) to determine number of rows with one integer divison
int rows = (len + columns - 1) / columns;
print_matrix(matrix, rows, columns);
encrypt(matrix, rows, columns, key);
print_matrix(matrix, rows, columns);
for (int row = 0; row < rows; row++) {
free(matrix[row]);
}
free(matrix);
return EXIT_SUCCESS;
}
$ gcc -Wall transposition.c
$ ./a.out
Enter your string: hello_there
Enter your key: KEY
Row 0: hel
Row 1: lo_
Row 2: the
Row 3: re*
Sorted key: EKY (length: 3)
Row 0: ehl
Row 1: ol_
Row 2: hte
Row 3: er*
$
You have a 2D array. The first axis is the list of strings. The second axis is the characters of a particular string. I assume when you mean swap column, you mean swap characters of a particular string for all strings.
In pseudo code:
for all strings i
temp = mat[i][some column]
mat[i][some column] = mat[i][someother column]
mat[i][someother column] = temp
I have an assignment to write code that printing all combinations of N char. For example, if the input is 3, the expected output must be "aaa aab aac aba ... ccc". But my code looping over and over again. Here's my code.
#include <stdio.h>
#ifndef MAX
#define MAX 5
#endif
void comb(char kar[], int size, int index) {
// string = aaa
// lim = 'd'
char lim = 'a' + size;
while (index != -1) {
if (kar[size-1] != lim) { // != c
for (int i = 0; i < size; i++) {
printf("%s ", kar);
kar[size-1]+=1;
}
return comb(kar, size, index);
} else {
while (kar[index-1] == lim && index != -1) {
kar[index-1]='a';
index--;
}
kar[index-1] += 1;
return comb(kar, size, size);
}
}
}
int main(int argc, char const *argv[]) {
int n;
char kar[MAX];
printf("Input N char : ");
scanf(" %d", &n);
for (int j = 0; j < n; j++) {
kar[j] = 'a';
}
comb(kar, n, n);
return 0;
}
I'm a little bit confused and I have no idea where is the mistake. Thank you.
The problem has been solved. I changed some elements in the comb() and added the pow() function to define the recursion limit.
int comb(char kar[], int size, int index, int limit) {
char lim = 97 + size;
int limit_value = pow(size,size);
if(limit == limit_value){
return 1;
} else {
if (index < size-1) {
printf("%s ", kar);
kar[size-1]+=1;
return comb(kar, size, index+1, limit+1);
} else {
int cek = index;
printf("%s ", kar);
while (kar[cek] == lim-1 ) {
kar[cek]=97;
cek-=1;
}
kar[cek] += 1;
return comb(kar, size, 0, limit+1);
}
}
}
So my attempt was that creating a program that automatically gets two matrixes' size from a .txt file and multiplies them. I could make the program with given sizes so in itself I only have problem with counting the cols and rows.
The input something like (MxN matrix):
1 2 3 4
1 2 3 4
1 2 3 4
To be specific, here is my program so far (the beginning of the code is relevant I think):
#include <stdio.h>
#include <stdlib.h>
struct mat1
{
int cols;
int rows;
};
struct mat2
{
int cols;
int rows;
};
struct mat1 dim1(const char* file)
{
struct mat1 m1;
int rows = 0;
int cols = 0;
char c;
FILE *f = fopen(file, "r+");
while((c = fgetc(f) != EOF))
{
if(c != '\n' && rows == 0)
{
cols++;
}
else if(c == '\n')
rows++;
}
rows++;
return m1;
}
struct mat2 dim2(const char* file)
{
struct mat2 m2;
int rows = 0;
int cols = 0;
char c;
FILE *f = fopen(file, "r+");
while((c = fgetc(f) != EOF))
{
if(c != '\n' && rows == 0)
{
cols++;
}
else if(c == '\n')
rows++;
}
rows++;
return m2;
}
double* alloc_matrix(int cols, int rows) {
double* m = (double*)malloc(cols * rows * sizeof(double));
if (m == 0) {
printf("Memory allocation error.\n");
exit(-1);
}
return m;
}
void read_matrix(FILE* f, double* m, int cols, int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
fscanf(f, "%lf", &m[i * cols + j]);
}
}
}
void multiplication(double* m1, double* m2, double* m3, int cols, int rows) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
m3[i * cols +j]=0;
for(int k = 0; k < cols; k++) {
m3[i * cols +j]+=m1[i * cols +k]*m2[k * cols +j];
}
}
}
}
void write_matrix(double* m, int cols, int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%f ", m[i * cols + j]);
}
printf("\n");
}
}
int main(int argc, char* argv[])
{
char* matrix1 = argv[1];
char* matrix2 = argv[2];
if (argc < 3) {
printf("Not enough arguments.\n");
exit(-1);
}
struct mat1 m1 = dim1(matrix1);
struct mat2 m2 = dim2(matrix2);
printf(" %d %d \n", m1.cols, m1.rows);
printf(" %d %d \n", m2.cols, m2.rows);
int c1 = m1.cols;
int r1 = m1.rows;
int c2 = m2.cols;
int r2 = m2.rows;
if (r1!=c2)
{
printf("Matrixes are not suitable for multiplication. \n");
exit(-1);
}
double* mtx1 = alloc_matrix(c1, r1);
double* mtx2 = alloc_matrix(c2, r2);
FILE* f1 = fopen(matrix1, "r");
if (f1 == 0)
{
printf("Cannot open file %s.", argv[1]);
exit(-1);
}
FILE* f2 = fopen(matrix2, "r");
if (f1 == 0)
{
printf("Cannot open file %s.", argv[1]);
exit(-1);
}
read_matrix(f1, mtx1, c1, r1);
read_matrix(f2, mtx2, c2, r2);
double* mtx3 = alloc_matrix(c1, r2);
multiplication(mtx1, mtx2, mtx3, c1, r2);
write_matrix(mtx3, c1, r2);
free(mtx1);
free(mtx2);
free(mtx3);
fclose(f1);
fclose(f2);
return 0;
}
When I tried it out with 2 3x3 matrixes, The outpot:
6422164 4199040 (from 2 printf()s that I set to check the dimensions).
6422164 4199040
Matrixes are not suitable for multiplication. (it's irrelevant)
So basically it doesn't use 3x3.
I cannot figure out what the problem is.
This is prefaced by my top comments.
I had to refactor dim to handle an arbitrarily large matrix, so I had to scan the first line of the file char-by-char, counting whitespace strings (which yields the number of columns - 1). It handles/strips leading/trailing whitespace [malformed]
I had dim then rewind the file and use fscanf and realloc to create the matrix dynamically.
Here's the working code [please pardon the gratuitous style cleanup]:
#include <stdio.h>
#include <stdlib.h>
struct mat {
int cols;
int rows;
double *m;
};
// size and read in matrix
struct mat
dim(const char *file)
{
struct mat m;
int rows = 0;
int cols = 0;
int maxcnt;
int curcnt;
int ret;
int c;
int c2;
FILE *f = fopen(file, "r+");
// strip leading whitespace [if any] off first line
while (1) {
c = fgetc(f);
if (c == EOF)
break;
if (c == '\n')
break;
if (c != ' ')
break;
}
// scan first line and count columns (number of space separaters)
while (1) {
c2 = ' ';
while (1) {
c = fgetc(f);
if (c == EOF)
break;
if (c == '\n') {
if (c2 != ' ')
++cols;
break;
}
if (c == ' ') {
if (c != c2)
++cols;
break;
}
c2 = c;
}
if (c == '\n')
break;
}
// convert number of whitespace separaters into number of columns
if (cols > 0)
++cols;
rewind(f);
m.rows = 0;
m.cols = cols;
m.m = NULL;
curcnt = 0;
maxcnt = 0;
while (1) {
if (curcnt >= maxcnt) {
maxcnt += m.cols * 100;
double *tmp = realloc(m.m,sizeof(double) * maxcnt);
if (tmp == NULL) {
printf("dim: realloc failure\n");
exit(1);
}
m.m = tmp;
}
ret = 0;
for (int idx = 0; idx < cols; ++idx, ++curcnt) {
ret = fscanf(f, "%lf", &m.m[curcnt]);
if (ret != 1)
break;
}
if (ret != 1)
break;
rows += 1;
}
fclose(f);
m.rows = rows;
// trim matrix to actual size;
m.m = realloc(m.m,sizeof(double) * rows * cols);
return m;
}
double *
alloc_matrix(int cols, int rows)
{
double *m = (double *) malloc(cols * rows * sizeof(double));
if (m == 0) {
printf("Memory allocation error.\n");
exit(-1);
}
return m;
}
void
multiplication(double *m1, double *m2, double *m3, int cols, int rows)
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
m3[i * cols + j] = 0;
for (int k = 0; k < cols; k++) {
m3[i * cols + j] += m1[i * cols + k] * m2[k * cols + j];
}
}
}
}
void
write_matrix(double *m, int cols, int rows)
{
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%f ", m[i * cols + j]);
}
printf("\n");
}
}
int
main(int argc, char *argv[])
{
if (argc < 3) {
printf("Not enough arguments.\n");
exit(1);
}
struct mat m1 = dim(argv[1]);
struct mat m2 = dim(argv[2]);
printf(" %d %d \n", m1.cols, m1.rows);
printf(" %d %d \n", m2.cols, m2.rows);
int c1 = m1.cols;
int r1 = m1.rows;
int c2 = m2.cols;
int r2 = m2.rows;
if (r1 != c2) {
printf("Matrixes are not suitable for multiplication.\n");
exit(-1);
}
double *mtx3 = alloc_matrix(c1, r2);
multiplication(m1.m, m2.m, mtx3, c1, r2);
write_matrix(mtx3, c1, r2);
free(m1.m);
free(m2.m);
free(mtx3);
return 0;
}
Here are two test files I used. Note that although you can't see it, the first line has trailing whitespace [as a test]:
This is m1.txt:
1 2 3 4
5 6 7 8
9 10 11 12
Here is the second file:
1 2 3
4 5 6
7 8 9
10 11 12
Here is the program output:
4 3
3 4
38.000000 44.000000 202.000000 232.000000
98.000000 116.000000 438.000000 504.000000
158.000000 188.000000 674.000000 776.000000
9.000000 10.000000 87.000000 100.000000
UPDATE:
Here's an alterate dim function that replaces the [somewhat fragile] char-by-char scan of the first line with a scan for newline [to get line length], followed by malloc of a buffer, fgets, and then loop on strtok to count the non-space strings in the lines (i.e. the number of columns):
// size and read in matrix
struct mat
dim(const char *file)
{
struct mat m;
int rows = 0;
int cols = 0;
int maxcnt;
int curcnt;
int ret;
char *buf;
char *bp;
char *tok;
int c;
int c2;
FILE *f = fopen(file, "r+");
// count number of chars in first line of the file
curcnt = 0;
while (1) {
c = fgetc(f);
if (c == EOF)
break;
++curcnt;
if (c == '\n')
break;
}
++curcnt;
buf = malloc(curcnt);
rewind(f);
fgets(buf,curcnt,f);
cols = 0;
bp = buf;
while (1) {
tok = strtok(bp," \n");
if (tok == NULL)
break;
++cols;
bp = NULL;
}
free(buf);
rewind(f);
m.rows = 0;
m.cols = cols;
m.m = NULL;
curcnt = 0;
maxcnt = 0;
while (1) {
if (curcnt >= maxcnt) {
maxcnt += m.cols * 100;
double *tmp = realloc(m.m,sizeof(double) * maxcnt);
if (tmp == NULL) {
printf("dim: realloc failure\n");
exit(1);
}
m.m = tmp;
}
ret = 0;
for (int idx = 0; idx < cols; ++idx, ++curcnt) {
ret = fscanf(f, "%lf", &m.m[curcnt]);
if (ret != 1)
break;
}
if (ret != 1)
break;
rows += 1;
}
fclose(f);
m.rows = rows;
// trim matrix to actual size;
m.m = realloc(m.m,sizeof(double) * rows * cols);
return m;
}
UPDATE #2:
I didn't like either solution for getting the number of columns, so here is a cleaner one that is as fast as the first one but is simpler and less cumbersome:
// scan first line and count columns
int
colcalc(FILE *f)
{
int c;
int noncur;
int nonprev = 0;
int cols = 0;
while (1) {
c = fgetc(f);
if (c == EOF)
break;
if (c == '\n')
break;
// only count non-whitespace chars
switch (c) {
case ' ':
case '\t':
noncur = 0;
break;
default:
noncur = 1;
break;
}
// column starts on _first_ char in word
if (noncur)
cols += (noncur != nonprev);
nonprev = noncur;
}
rewind(f);
return cols;
}
UPDATE #3:
I tried out the previous 2 methods by you and it works so smoothly! Thank you once again! and your comments about making my program simpler with less variables and stuff!
You're welcome!
My coding style/methodology comes from a [very] old book: "The Elements of Programming Style" by Kernighan and Plauger.
The examples from that book are written in Fortran, but the maxims are on par with "Code Complete" by Steve McConnell.
From Chapter 7 [Efficiency and Instrumentation]:
Make it right before you make it faster.
Keep it right when you make it faster.
Make it clear before you make it faster.
Don't sacrifice clarity for small gains in "efficiency".
Don't strain to re-use code; reorganize instead.
Make sure special cases are truly special.
Keep it simple to make it faster.
Don't diddle code to make it faster -- find a better algorithm.
Instrument your programs. Measure before making "efficiency" changes.
I know that I can scanf certain amount of numbers with scanf for example for 3 numbers
scanf("%d %d %d",array[0],array[1],array[2]);
but how can I scan it if I didn't know how many numbers (integer, not float) I would input into an array before enter (NOT EOF)? for example
input : 12 43 23(enter) --> array[0]=12, array[1]=43, array[2]=23
input : 10 20 30 40 50(enter) --> array[0]=10, array[1]=20, array[2]=30, array[3]=40, array[4]= 50
etc..
It's about how to input the numbers into an integer array.
And if it's possible, I want to save it into an 2 dimensions array, for example
input : 12 43 23(enter) --> array[0][0]=12, array[0][1]=43, array[0][2]=23
input : 10 20 30 40 50(enter) --> array[1][0]=10, array[1][1]=20, array[1][2]=30, array[1][3]=40, array[1][4]= 50
Here is come code showing how to scan the integers into a 2D array:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INITSIZE 5
#define BUFFSIZE 1000
void print_and_free(int **array, int rowsize, int colsize);
void check_ptr(void *ptr, const char *msg);
int
main(void) {
int **array;
size_t rowsize = INITSIZE, colsize = INITSIZE;
int row = 0, col, numdigits;
char buffer[BUFFSIZE];
char *number;
array = malloc(rowsize * sizeof(*array));
check_ptr(array, "Allocation");
printf("Enter digits(Enter blank line to end):\n");
while (fgets(buffer, BUFFSIZE, stdin) != NULL && strlen(buffer) != 1) {
col = 0;
numdigits = 0;
if (rowsize == row) {
rowsize *= 2;
array = realloc(array, rowsize * sizeof(*array));
check_ptr(array, "Reallocation");
}
array[row] = malloc(colsize *sizeof(int));
check_ptr(array[row], "Allocation");
number = strtok(buffer, " ");
while (number != NULL) {
numdigits++;
if (colsize == numdigits) {
colsize *= 2;
array[row] = realloc(array[row], colsize * sizeof(int));
check_ptr(array[row], "Reallocation");
}
array[row][col] = atoi(number);
col++;
number = strtok(NULL, " ");
}
row++;
}
print_and_free(array, row, col);
return 0;
}
void
print_and_free(int **array, int rowsize, int colsize) {
int row, col;
printf("Your numbers:\n");
for (row = 0; row < rowsize; row++) {
for (col = 0; col < colsize; col++) {
printf("array[%d][%d] = %d", row, col, array[row][col]);
if (col != colsize - 1) {
printf(", ");
}
}
free(array[row]);
array[row] = NULL;
printf("\n");
}
free(array);
}
void
check_ptr(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
Here's how you can store things in a (dynamically allocated) array. This does assume that the line length is limited to 1000 chars though. (Code adapted from How do I use scanf() to take an arbitrary amount of integers?)
#include <stdio.h>
#include <stdlib.h>
int main() {
int val_size = 2;
int* vals = (int*)malloc(val_size * sizeof(int)); // initial array size
char buffer[1000]; // for reading in the line
int pos, bytes_read, num;
int num_read = 0;
if (fgets(buffer, sizeof(buffer), stdin) != 0) {
for (pos = 0; sscanf(buffer+pos, "%d%n", &num, &bytes_read) != EOF; pos += bytes_read) {
// resize the array if needed
if (num_read >= val_size) {
val_size *= 2;
vals = (int*)realloc(vals, val_size * sizeof(int));
}
// store the value in the array
vals[num_read] = num;
num_read++;
}
}
// print the values to prove it works
for (int i = 0; i < num_read; i++) {
printf("%d ", vals[i]);
}
printf("\n");
free(vals); // important after you're done with it
}
You can wrap a while around the if to get multiple lines.
You may use a while loop and check for the return value of scanf. For example:
int num = 0;
int idx = 0;
int arr[100] = { 0 };
while( scanf( "%d", &num ) == 1 )
{
arr[idx++] = num;
if( idx == 99 ) // protect from array overflow
{
break;
}
}
for( int i = 0; i < idx; i++ )
{
printf( "%d\n", arr[i] );
}
I'm trying to read specific chars inside a file redirected from stdin into a 2D array, I'm not sure if I'm allocating the memory for the 2D array properly. The first line inside the file is the dimensions of the matrix I'm trying to copy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "QueueImplementation.c"
int tester(char *s, int cnt)
{
int num1, num2;
if(cnt == 0)
{
sscanf(s, "%d %d", &num1, &num2);
if(num1 < 2 || num1 > 20 || num2 < 2 || num2> 20)
{
printf("Incorrect Matrix Dimensions!");
printf("\n");
}
return num1;
}
}
void allocateMem(char ***cell, int n, int m)
{
*cell=(char**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*cell[i]=(char*)malloc(m*sizeof(int));
}
int main(){
char buffer[200];
int j,max_row,max_col;
int count = 0;
int i = 0;
while (fgets(buffer, sizeof buffer, stdin))
{
if(count == 0)
max_col = tester(buffer, count);
count++;
}
max_row = count - 1;
char** cell;
allocateMem(&cell, max_row, max_col);
while (fgets(buffer, sizeof buffer, stdin))
{
for(j = 0;j<max_col;j++)
{
if(buffer[j] != '\n' && buffer[j] != ' ' && buffer[j] < '0')
cell[i-1][j] = (char) buffer[j];
}
i++;
}
for (i = 0;i<max_row;i++)
{
for (j = 0;j<max_col;j++)
{
printf("%c", cell[i][j]);
}
}
}
Test file that I redirect consists of
12 10
oooooooooooo
ooooooooooo.
oooooooo....
se.......ooo
oooooooo....
Mainly consists of "o" and "." except for a single "s" and "e". The 12 and 10 are the dimensions of the matrix that I am trying to copy, so the expected output should be the matrix consisting the o's and .'s along with a single "s" and "e".
fix like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void tester(char *s, int *cols, int *rows){
int cnt;
cnt = sscanf(s, "%d %d", cols, rows);
if(cnt != 2 || *cols < 2 || *cols > 20 || *rows < 2 || *rows > 20){
printf("Incorrect Matrix Dimensions!\n");
exit(EXIT_FAILURE);//The program can not be continued.
}
}
void allocateMem(char ***cell, int n, int m){
*cell = malloc( n * sizeof(char*));
for(int i = 0; i < n; i++)
(*cell)[i] = malloc(m * sizeof(char));
}
int main(void){
char buffer[200] = "";
char **cell;
int max_row, max_col;
int i, j;
fgets(buffer, sizeof buffer, stdin);//read first line
tester(buffer, &max_col, &max_row);//If fgets fails, this also fails
allocateMem(&cell, max_row, max_col);
for(i = 0; i < max_row; ++i){
for(j = 0; j < max_col; j++){
int ch = fgetc(stdin);
if(!isspace(ch))
cell[i][j] = ch;
else
--j;//cancel this turn
}
}
for (i = 0; i < max_row; i++){
for (j = 0; j < max_col; j++){
printf("%c", cell[i][j]);
}
puts("");//put newline
}
//deallocate cell
}