How can multiple strings be stored in C?
if we consider that the number of strings are taken from user , how can we save them in c language , considering that we had not declared any char strings before asking the number of strings from user , because the number of strings was not available.here is what i did but i ended up printing the first character of strings.
#include <stdio.h>
int main()
{
int a;
scanf("%d",&a);
char array[a][1];
for(int i = 0 ; i < a ; i++)
{
for(int j = 0 ; j < 1 ; j++)
{
scanf("%s",&array[i][j]);
}
}
for(int i = 0 ; i < a ; i++)
{
for(int j = 0 ; j < 1 ; j++)
{
printf("%c",array[i][j]);
}
printf("\n");
}
}
Let's start from the beginning.
I don't think you really understand what is char though. Char is only ONE character. So things like char array[16][1] mean that you have array of 16 strings where each string have maximum length of one. Also your next step scanf("%s", &array[i][j]); doesn't make sense, since you're getting multiple symbols as an input, but you're writing only to single character. Proper solution would be something like this:
char array[a][255]; // 255 will be maximum length of one 'string'
for(int i = 0; i < a; ++i) {
scanf("%s", array[i]);
}
As you can see, you don't need & sign here, because array[i] already returns address of the first character in the string. The same thing applies to printing. Proper way is to do following thing:
for(int i = 0; i < a; ++i) {
printf("%s\n", array[i]);
}
Your solution only displays one character.
And remember, char is just basic number, ranging typically from 0-255 (if compiler defaults char to unsigned char). Your code implies that you treat char as a full C++ string, which it definitely isn't.
Related
So I have a 2D array that I want to use later. Right now I just want to fill the empty spots.
So far I've just been messing around with array types and different default values. From my understanding a new array is filled with '0', I have tried NULL aswell.
int r = 5;
int c = 5;
int i;
int j;
int k = 0;
int area = r*c;
const char *array[r][c]; //tried char array[r][c] and other types
Setup my initial values and array here.
while(k< area){
for (j = 0; j < c; j++){
for (i = 0; i<r; i++){
if (array[i][j] == 0){
board[i][j] = ".";
}
printf("%c",aray[i][j]);
if (i = r - 1){
printf("\n");
}
k++;
}
}
}
This is where I try replacing all non filled values (all of them at this point) with ".", so the output should be a row of 5x5 dots. Instead I get weird letters and numbers. I have tried %s insead of %c, and no luck there but the output was different. Where I do %s I get some dots, but still not on a grid and the weird values show up.
Also Im pretty sure printf in a for loop, by default does it on a new line so I won't get the grid, so is there a better way of doing this?
What you have is an array of pointers. This would be suitable for a 2D array of strings, but not for a 2D array of characters. This isn't clear from your question, so I'll assume that you actually want a 2D array of characters. The syntax is: char array [r][c];.
Notably, since you used r and c which are run-time variables, this array is a variable-length array (VLA). Such an array cannot be placed at file scope ("global"). Place the array inside a function like main().
In order to use VLA you must also have a standard C compiler. C++ compilers and dinosaur compilers won't work.
Since you will have to declare the VLA inside a function, it gets "automatic storage duration". Meaning it is not initialized to zero automatically. You have to do this yourself, if needed: memset(array, 0, sizeof array);. But you probably want to initialize it to some specific character instead of 0.
Example:
#include <stdio.h>
#include <string.h>
int main (void)
{
int r = 5;
int c = 5;
char array [r][c];
memset(array, '#', sizeof array);
for(size_t i=0; i<r; i++)
{
for(size_t j=0; j<c; j++)
{
printf("%c", array[i][j]);
}
printf("\n");
}
}
Output:
#####
#####
#####
#####
#####
From my understanding a new array is filled with '0'
const char *array[r][c];
No*, you have fill it yourself in a double for loop, like this:
for(int i = 0; i < r; ++i)
for(int j = 0; j < c; ++j)
array[i][j] = 0
since your structure is a variable sized array.
Instead I get weird letters and numbers
This happens because your code invokes Undefined Behavior (UB).
In particular, your array is uninitialized, you then try to assign cells to the dot character, if their value is already 0.
Since the array is not initialized, its cells' values are junk, so none satisfied the condition of been equal to 0, thus none was assigned with the dot character.
You then print the array, which still contains garbage values (since it was never really initialized by you), and the output is garbage values.
* As stated by #hyde, this is true for local non-static arrays (which is most probably your case). Statics and globals are default initialized (to zero if that was the case here).
You have several problems:
You are declaring a pointer to the array you want, not the array
Whenever R and C are not compile time known, you can't use a built in array. You might can however use VLAs (C99 as only C standard has VLAs mandatory, C11 made them optional again), which seems like a built in array with a size not known at compile time, but has very important implications, see : https://stackoverflow.com/a/54163435/3537677
Your array is only zero filled, when declared as a static variable.
You seem to have mistake the assign = operator with the equal == operator
So by guessing what you want:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define R 5
#define C 5
int r = R;
int c = C;
int i;
int j;
int k = 0;
int area = R*C;
const char array[R][C];
int main() {
while(k< area){
for (j = 0; j < c; j++){
for (i = 0; i<r; i++){
if (array[i][j] == 0){
}
printf("%c",array[i][j]);
if (i == r - 1){
printf("\n");
}
k++;
}
}
}
//or
char** dynamic_array = malloc(r * c);
if (dynamic_array == NULL) {
perror("Malloc of dynamic array failed");
return EXIT_FAILURE;
}
memset(dynamic_array, '0', r*c);
k = 0;
while(k< area){
for (j = 0; j < c; j++){
for (i = 0; i<r; i++){
if (dynamic_array[i][j] == 0){
}
printf("%c",dynamic_array[i][j]);
if (i == r - 1){
printf("\n");
}
k++;
}
}
}
return 0;
}
I'm trying to write a program that analyzes a (3 x 4) matrix of strings provided by the user. Ultimately, it needs to output the longest string present in the matrix, along with that string's length.
My program seems to read the input correctly, as judged its success in echoing back the input strings, but it does not correctly output the longest word. I'm sure I'm committing some kind of pointer-related error when I pass the value of longest word, but I do not have any idea how to solve it.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define M 4
#define N 5
#define MAX_DIM 20
void findMAX(char matrice[N][M][MAX_DIM]) {
char maxr;
int index;
int i, j, it;
index = 0;
maxr = *(*(*(matrice+0)+0)+MAX_DIM);
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
if (index < strlen(matrice[i][j])) {
index = strlen(matrice[i][j]);
// I save the longer line's value
it = i;
// I save the maximum's value
maxr = *(*(*(matrice+i)+j)+MAX_DIM);
}
}
}
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
printf ("It is content in the: %d line, which is: \n", it);
for (j = 0; j < N-1; j++) {
printf("%s ", matrice[it][j]);
}
}
void leggi(char matrice[N][M][MAX_DIM]) {
int i, j;
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
printf ("Insert the element matrix [%d][%d]: ", i, j);
scanf ("%s", matrice[i][j]);
fflush(stdin);
}
}
}
void stampa(char matrice[N][M][MAX_DIM]) {
int i, j;
printf("\n(4 x 3) MATRIX\n");
for (i = 0; i < N-1; i++) {
for (j = 0; j < M-1; j++) {
printf("%s ", matrice[i][j]);
}
printf("\n\n");
}
}
int main(int argc, char *argv[]) {
char matrix[N][M][MAX_DIM]; //Matrix of N*M strings, which are long MAX_DIM
printf("************************************************\n");
printf("** FIND THE LINE WITH THE MAXIMUM ELEMENT **\n");
printf("** IN A (4 x 3) MATRIX **\n");
printf("************************************************\n");
printf ("Matrix Reading & Printing\n");
leggi (matrix);
stampa (matrix);
findMAX(matrix);
return 0;
}
First of all to address some misconceptions conveyed by another answer, consider your 3D array declared as
char matrix[N][M][MAX_DIM];
, where N, M, and MAX_DIM are macros expanding to integer constants.
This is an ordinary array (not a variable-length array).
If you want to pass this array to a function, it is perfectly acceptable to declare the corresponding function parameter exactly the same way as you've declared the array, as indeed you do:
void findMAX(char matrice[N][M][MAX_DIM])
But it is true that what is actually passed is not the array itself, but a pointer to its first element (by which all other elements can also be accessed. In C, multidimensional arrays are arrays of arrays, so the first element of a three-dimensional array is a two-dimensional array. In any case, that function declaration is equivalent to both of these:
void findMAX(char (*matrice)[M][MAX_DIM])
void findMAX(char matrice[][M][MAX_DIM])
Note in particular that the first dimension is not conveyed. Of those three equivalent forms, I find the last clearest in most cases.
It is quite odd, though, the way you access array elements in your findMAX() function. Here is the prototypical example of what you do:
maxr = *(*(*(matrice+i)+j)+MAX_DIM);
But what an ugly and confusing expression that is, especially compared to this guaranteed-equivalent one:
maxr = matrice[i][j][MAX_DIM];
Looking at that however, and it how you are using it, I find that although the assignment is type-correct, you are probably using the wrong type. maxr holds a single char. If you mean it to somehow capture the value of a whole string, then you need to declare it either as an array (into which you will copy strings' contents as needed), or as a pointer that you will set to point to the string of interest. The latter approach is more efficient, and I see nothing to recommend the former for your particular usage.
Thus, I think you want
char *maxr;
... and later ...
maxr = matrice[0][0];
... and ...
maxr = matrice[i][j];
That sort of usage should be familiar to you from, for example, your function stampo(); the primary difference is that now you're assigning the expression to a variable instead of passing it directly to a function.
And it turns out that changing maxr's type that way will correct the real problem here, which #AnttiHaapala already pointed out in comments: this function call ...
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
requires the second argument (maxr) to be a pointer to a null-terminated array of char in order to correspond to the %s directive in the format string. Before, you were passing a single char instead, but with this correction you should get mostly the expected result.
You will probably, however, see at least one additional anomaly. You final loop in that function has the wrong bound. You are iterating with j, which is used as an index for the second dimension of your array. That dimension's extent is M, but the loop runs to N - 1.
Finally, I should observe that it's odd that you allocate space for a 5 x 4 array (of char arrays) and then ignore the last row and column. But that's merely wasteful, not wrong.
Try something like this:
void findMAX(char matrice[N][M][MAX_DIM]){
// char maxr
char maxr[MAX_DIM];
int index;
int i, j, it;
index = 0;
// maxr = *(*(*(matrice+0)+0)+MAX_DIM);
strncpy(maxr, *(*(matrice+0)+0), MAX_DIM);
for (i = 0; i < N-1; i++)
{
for (j = 0; j < M-1; j++)
{
if (index < strlen(matrice[i][j]))
{
index = strlen(matrice[i][j]);
it = i;
// maxr = *(*(*(matrice+i)+j)+MAX_DIM);
strncpy(maxr, *(*(matrice+i)+j), MAX_DIM);
}
}
}
printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
printf ("It is content in the: %d line, which is: \n", it);
// for (j = 0; j < N-1; j++){
for (j = 0; j < M-1; j++){
printf("%s ", matrice[it][j]);
}
}
It's possible to pass multi-dimensional arrays to C functions if the size of the minor dimensions is known at compile time. However the syntax is unacceptable
void foo( int (*array2d)[6] )
Often array dimensions aren't known at compile time and it is necessary to create a flat array and access via
array2D[y*width+x]
Generally it's easier just to use this method even if array dimensions are known.
To clarify in response to a comment, C99 allows passing of variable size arrays using the more intuitive syntax. However the standard isn't supported by Microsoft's Visual C++ compiler, which means that you can't use it for many practical purposes.
I'm trying to get an input from the user and store it in a certain place in a 2d Array called Matrix. The Compiler says:
error: assignment makes integer from pointer without a cast [-Werror]
Matrix[i][j]=matrixinput;
This is the part of my Program:
int i=0;
int j=0;
char size[1];
char matrixinput[1];
int sizeint=0;
int Matrix[10][10];
while (i<=(sizeint-1) && j<=(sizeint-1)){
gets(matrixinput);
Matrix[i][j]=matrixinput;
j++;
if (j==(sizeint-1)){
j=0;
i++; }
else {continue;};
};
I am just a Student with basically 0 expeience in c or any kind of programming, so maybe somebody can help me to find out how I can fix this.
Matrix[i][j]=matrixinput;
What you are doing is assign a char array of size 1 to an int. Your compiler issues a warning for this.
Don't assign arrays like this .
You want to take input in 2-d array, directly take inout in it using scanf -
scanf("%d",&Matrix[i][j]);
And this loop -
while (i<=(sizeint-1) && j<=(sizeint-1)){
This loop won't iterate for once , because condition will remain always flase as sizeint-1 is -1 as sizeint is -1 . So , you need to work on this condition also .
Note - Increase your array's size and don't use gets , use fgets instead.
A professor gave me good tip for debug this type of error, ask you if the left operator type is equals to the right operator type. in your code it's false because right operator equals integer and left operator equals character.
What you could do to remove the error is: Matrix[i][j] = (int) matrixinput[0]; (Array indexing starts with 0)
But your code will still not work because you have initialized i and j to 0 and also sizeint. It means that, in the loop while (i<=(sizeint-1) && j<=(sizeint-1)), you are basically checking if 0 <= -1 which is impossible and so your while loop will never execute. What you could do is:
gets(matrixinput);
for(i = 0; i < 10; i++)
{
for(j = 0; j < 10; j++)
{
if(i == 0 && j == 0) { //say you want to put the char at the first row first column
Matrix[i][j] = matrixinput[0];
}
}
}
You could also use scanf() instead of gets().
here is one possible correction to the posted code
It removes unneeded clutter from the code
It makes use of scanf() so no char to int conversion needed in the code
It consistently indents the code
It #defines the size of the matrix to make the code clearer
Note: it fails to check the returned value (not the parameter value) from scanf() to assure the input/conversion was successful
#define MATRIX_SIZE (10)
// int i=0;
// int j=0;
// char size[1];
// char matrixinput[1];
// int sizeint=0;
//int Matrix[10][10];
int Matrix[MATRIX_SIZE][MATRIX_SIZE];
// while (i<=(sizeint-1) && j<=(sizeint-1)){
// gets(matrixinput);
// Matrix[i][j]=matrixinput;
// j++;
// if (j==(sizeint-1)){
// j=0;
// i++; }
// else {continue;};
//};
for( int i=0; i<MATRIX_SIZE; i++)
{
for( int j=0; j<MATRIX_SIZE; j++)
{
scanf( "%d", Matrix[i][j]);
}
}
I wrote a small program to combine two 2d arrays. Here is the code:
#define MAX 7
int main(void) {
int i, j;
char *array1[] = {"Welt,", "bist", "du"};
char *array2[] = {"noch", "zu", "retten?"};
char final[MAX][MAX];
for(i = 0; i < 3; i++) {
// initialize ith names element with first name
strcpy(final[i], array1[i]);
}
for(j = 0; j < 3; j++) {
// concatenate the last name to the firstname+space string
strcat(final[i], array2[j]);
}
for (i = 0; i != 6; i++) {
printf("%s", final[i]);
}
return EXIT_SUCCESS;
}
I get really strange output like:
Welt,bistbistdunochzuretten?uretten?en?
while what I want is this:
Welt,bistdunochzuretten
As you can see it is not completely wrong. There should not be a space between the words.
How can I fix my code?
The problems were that in the second for you were doing strcat(final[3], array2[j]);, because i was 3 at that point and in the final for you were trying to print from final[0] to final[5], when you only had defined final[0] to final[3] (where on final[0] to final[2] you had the names, and in final[3] you had all the last names concatenated which also exceeded the limit of characters), and without printing them in a new line it was hard to tell which string was what.
Try this.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 7
int main(void) {
int i,j;
char *array1[] = {"Welt","bist","du"};
char *array2[] = {"noch","zu","retten?"};
char final[MAX][MAX];
for(i=0;i<3;i++)
strcpy(final[i], array1[i]); //To initialize ith names element with first name
for(j=0;j<3;j++)
strcat(final[j],array2[j]); //Concatanate the last name to the firstname+ space string
for (i = 0; i < 3; i++)
printf("%s\n", final[i]);
return EXIT_SUCCESS;
}
There are several problems with your code:
The constant MAX is not large enough for your data. The string "retten?" contains seven characters plus one terminating byte. As such, MAX must be at least 8, otherwise you get undefined behavior.
Your second loop contains uses the wrong index into final[i]. See point 3. for corrected versions.
The use of strcat() is wrong, you should be using strcpy() just like in the first loop. Together with point 2., your second loop should either look like this:
for(j = 0; j < 3; i++, j++) { //add increment for i
strcpy(final[i], array2[j]);
}
or like this:
for(j = 0; j < 3; j++) {
strcpy(final[3 + j], array2[j]); //derive the index from j
}
Regarding Point 1, I always advise against using any compile time constants like MAX. My experience is that these are just bugs that are waiting to strike. Someday, someone will have a use case that exceeds the limit, and your program goes boom. I always allocate buffers to fit the strings that I need to store, leaving the available RAM as the only limit to my code. To this end, functions like strdup() and asprintf() are extremely handy because they already do the allocation for me.
Regarding Point 2, you should try to declare all your loop variables right inside the initialization statement. Like so:
for(int i = 0; i < 3; i++) {
// initialize ith names element with first name
strcpy(final[i], array1[i]);
}
That way you don't run the danger of inadvertently using the loop variable after the loop / forgetting the initialization, etc. because your compiler will complain about the unknown variable.
I am having trouble with a homework question that I've been working at for quite some time.
I don't know exactly why the question is asking and need some clarification on that and also a push in the right direction.
Here is the question:
(2) Solve this problem using one single subscripted array of counters. The program uses an array of characters defined using the C initialization feature. The program counts the number of each of the alphabetic characters a to z (only lower case characters are counted) and prints a report (in a neat table) of the number of occurrences of each lower case character found. Only print the counts for the letters that occur at least once. That is do not print a count if it is zero. DO NOT use a switch statement in your solution. NOTE: if x is of type char, x-‘a’ is the difference between the ASCII codes for the character in x and the character ‘a’. For example if x holds the character ‘c’ then x-‘a’ has the value 2, while if x holds the character ‘d’, then x-‘a’ has the value 3. Provide test results using the following string:
“This is an example of text for exercise (2).”
And here is my source code so far:
#include<stdio.h>
int main() {
char c[] = "This is an example of text for exercise (2).";
char d[26];
int i;
int j = 0;
int k;
j = 0;
//char s = 97;
for(i = 0; i < sizeof(c); i++) {
for(s = 'a'; s < 'z'; s++){
if( c[i] == s){
k++;
printf("%c,%d\n", s, k);
k = 0;
}
}
}
return 0;
}
As you can see, my current solution is a little anemic.
Thanks for the help, and I know everyone on the net doesn't necessarily like helping with other people's homework. ;P
char c[] = "This is an example of text for exercise (2).";
int d[26] = {0}, i, value;
for(i=0; i < sizeof(c) - 1; i++){ //-1 to exclude terminating NULL
value = c[i]-'a';
if(value < 26 && value >= 0) d[value]++;
}
for(i=0; i < 26; i++){
if(d[i]) printf("Alphabet-%c Count-%d\n", 'a'+i, d[i]);
}
Corrected. Thanks caf and Leffler.
The intention of the question is for you to figure out how to efficiently convert a character between 'a' and 'z' into an index between 0 and 25. You are apparently allowed to assume ASCII for this (although the C standard does not guarantee any particular character set), which has the useful property that values of the characters 'a' through 'z' are sequential.
Once you've done that, you can increment the corresponding slot in your array d (note that you will need to initialise that array to all-zeroes to begin with, which can be done simply with char d[26] = { 0 };. At the end, you'd scan through the array d and print the counts out that are greater than zero, along with the corresponding character (which will involve the reverse transformation - from an index 0 through 25 into a character 'a' through 'z').
Fortunately for you, you do not seem to be required to produce a solution that would work on an EBCDIC machine (mainframe).
Your inner loop needs to be replaced by a conditional:
if (c[i] is lower-case alphabetic)
increment the appropriate count in the d-array
After finishing the string, you then need a loop to scan through the d-array, printing out the letter corresponding to the entry and the count associated with it.
Your d-array uses 'char' for the counts; that is OK for the exercise but you would probably need to use a bigger integer type for a general purpose solution. You should also ensure that it is initialized to all zeros; it is difficult to get meaningful information out of random garbage (and the language does not guarantee that anything other than garbage will be on the stack where the d-array is stored).
char c[] = "This is an example of text for exercise (2).";
char d[26];
int i;
int j;
for(i = 0; i < 26; i++)
{
d[i] = 0; // Set the frequency of the letter to zero before we start counting.
for(j = 0; j < strlen(c); j++)
{
if(c[j] == i + 'a')
d[i]++;
}
if(d[i] > 0) // If the frequency of the letter is greater than 0, show it.
printf("%c - %d\n", (i + 'a'), d[i]);
}
.
for(s = 'a'; s < 'z'; s++){
j=0;
for(i = 0; i < sizeof(c); i++) {
if( c[i] == s )
j++;
}
if (j > 0)
printf("%c,%d\n", s, j);
}