Using 2d arrays to store strings in C - c

I want to make a program that handles strings in 2d arrays in the following manner:
Each row represents one name only, while columns holds separate characters of each name.
Like so:
0 1 2 3 4 5
0 K e v i n \0
1 J o h n \0
2 L u c y \0
Now, the way I understand arrays is that they work as pointers for the first element. So when I read the string using the readstring(name) function even though I used a 1D array, it should work as a pointer to the 2D array and store each string as I showed above, right?
The following code is supposed to ask for three names then print them all, but it only prints the last name and some gibberish, what did I do wrong?
#include <stdio.h>
#include <stdlib.h>
void readstring(char name[]);
void get_data(char name[][15]);
void show_data(char name[][15]);
int main()
{
char name[3][15];
get_data(name);
show_data(name);
return 0;
}
void get_data(char name[][15]){
int i=0;
for(i=0;i<3;i++){
printf("\nEnter name: ");
readstring(name);
}
}
void show_data(char name[][15]){
int i;
for(i=0;i<3;i++){
printf("%s",name[i]);
}
}
void readstring(char str[]){
int i=0;
while((str[i++]=getchar())!='\n' && i<15);
str[i]='\0';
}
The output shows like this:
http://i58.tinypic.com/e7i048.jpg

The problem is here:
readstring(name);
Change it to:
readstring(name[i]);
The problem is that name is a 2 - d array, or , an array of strings. Therefore, to access one string in the array of strings, you need to use an index for that particular string.
In fact, the calling function readstring() expects a string as an argument.

Related

How to find the total number of a certain element in an array(C)

I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)

Create an array of size N and then assign to each element the value "[ ]" [duplicate]

This question already has answers here:
Pointer to string changes its value unexpectedly
(4 answers)
Closed 4 years ago.
I would like to create an array in C and then assign to every value in that array the string "[ ]".
This is what I have in mind:
char Array[N];
for(int i = 0; i < N; i++)
{
Array[i]="[ ]";
}
What is the correct approach to doing that?
Bellow is a sample working code you customize to your taste:
#include<stdio.h>
#include<string.h> // for strcpy: use to copy one string into another
// set a symbolic constant
#define N 10
int main(int argc, char **argv)
{
// declare the array
char Array[N][4]; // 4, because "[ ]" is 3+1 long
for(int i=0; i < N; i++){
strcpy(Array[i], "[ ]");
}
// print out the content for test purpose
for(int i=0; i < N; i++){
printf("Array[%d] = %s\n", i, Array[i]);
}
return 0;
}
This question already has an accepted solution but I'd like to provide a bit more context that will help people who are used to higher-level languages like Java and C++ understand why these steps are needed when writing this algorithm in C vs. in a newer language.
For starters, not every C compiler will allow you to create an array with a size determined by a variable (this is called a Variable Length Array, or VLA--you can read more about them here: How do I declare a variable sized array in C?). Unfortunately you can't even declare a const variable for the number of terms you want in your array (read more about that here: Can a const variable be used to declare the size of an array in C?). So that's why you're stuck typing the literals everywhere in the program or using preprocessor commands like I've demonstrated.
Next, the length of a char array in C is the number of chars it can hold. However, since each of your terms is 3 characters long plus the null character at the end you need the array to be 4 times longer than the number of terms. You can use two See the code below for how to declare this.
Finally, you need to #include the string.h header file in order to be able to work with strings in C.
#include <stdio.h>
#include <string.h>
int main(){
#define N_TERMS 6
#define L_TERM 4
char term[L_TERM] = "[ ]";
char Array[N_TERMS * L_TERM] = ""; //array should be the size of the product of number of terms and length of term
for(int i = 0; i < N_TERMS; i++){
strcat(Array, term); //strcat adds the second string to the end of the first
}
printf("%s", Array); //prints the entire string
return 0;
}
A char is one character. Which would be in single quotes not double quotes. "[ ]" is three character. [, the space and ] are together three characters. Each index in a char array can only hold one character at a time, so the [ or the space or the ] or some other character.

A string of codes connected to multiple strings.I have some doubts about the two dimensional array and the for loop. Thank you very much!

/* link many strings*/
#include<stdio.h>
char *mystrcat(char * strDest, char * strSrc);
int main(void)
{
int n;
while(scanf("%d",&n))//输入要连接的字符串个数
{
if(n==0) break;//输入0结束
else
{
char words[n][100];
int i=0;
int j;
for(i=0;i<=n;i++)
{
while(fgets(words[i],100,stdin)!=NULL)
{
j=0;
while(words[i][j]!='\n')
j++;
if(words[i][j]=='\n') words[i][j]='\0';break;
}
}//输入字符串
for(i=n;i>0;i--)
{
mystrcat(words[i-1],words[i]);
}//连接这几个字符串
fputs(words[0],stdout);//输出字符串
printf("\n");
}
}
return 0;
}
//strcat函数原型
char *mystrcat(char * strDest,char * strSrc)
{
char *res=strDest;
while(*strDest)strDest++;
while(*strDest=*strSrc)
{
strDest++;
strSrc++;
}
return res;
}
This is a string of correct code to connect multiple strings. But I think n should be n-1 in two for cycles. But if you change the n to n-1, you can only enter n-1 strings, one less than I think. Can you tell me where my idea is wrong?
for(i=0;i<=n;i++)
Accessing array index out of bound when i=n - this is undefined behavior. So of course indexing should be from n-1 to 0( at max) or 0 to n-1.
And also array indexing in C starts from 0. So there are n elements that you are accessing, not n-1.
So corrections would be
for(i=0;i<=n-1;i++)
The thing is - you are reading in the n locations having index 0 to n-1 on the array and then you concatenate them one by one and at last all concatenated strings will be in words[0]. You are printing it out.
The second loop would be like
for(i=n-1;i>0;i--)
{
mystrcat(words[i-1],words[i]);
}
The idea is no matter what while accessing array indices don't access array index out bound. Here you can simply write it like this as shown in the second case. The thing is here we have ensured that all the indices used are from {0,1,2,3...,n-1}.
First determine what you want to do, if you want to take n string and then try to concatenate them then yes you can. That's what is being done here. but a much cleaner way to do it would be that keep a different result string on which you will concatenate n strings. That will not overwrite or change the already inputted strings.

Not Giving a proper output for every test case

Given an array of integers print each element in reverse order as a single line of space-separated integers.
Input Format
Output Format
Print all integers in in reverse order as a single line of space-separated integers.
Sample Input
4
1 4 3 2
Sample Output
2 3 4 1
Here's my Code
int main()
{
int n;
int a[n];
cin >>n;
for (int i=0;i<n;i++)
{
cin>>a[i];
}
for (int i=n-1;i>=0;i--)
cout<<a[i]<<" ";
return 0;
}
You can not allocate an static array with a variable size meaning the expression a[n] is not acceptable since in the compile time the variable "n" is not determined. If this question have a limit for "n" - for example n < 1000 - then replace the expression with int a[1000] ;. If it doesn't , replace it with int* a = new int[n] ;. It is called dynamic allocation , you can search it to find out how amazing it is ;)

iterating multi-dimensional arrays in C without knowing index

I'm having a problem processing a multidimensional array. I'm trying to get "123" "456" "x123" and "x456" to appear on screen inside a function using pointers:
void f(char ***array){
while (**array != '\0'){
while (*array != '\0'){
printf("%s\n",*array);array++;
}
}
}
int main(){
char* arr[50][50]={{"123","456"},{"X123","X456"}};
f(arr);
return 0;
}
When compiling, I receive the warning passing argument 1 of 'f' from incompatible pointer type at the line f(arr);. and when running the code, I see:
123
456
Segmentation fault
and the program exits.
When I change my code to this:
void f(char **array){
while (*array != '\0'){
printf("%s\n",*array);array++;
}
}
int main(){
char* arr[50]={"123","456"};
f(arr);
return 0;
}
The numbers iterate fine, but I'd rather group my data into sets at some point for better organization. Why does the first set of code with multidimensional array not execute properly?
First, why three stars? What is it that you are trying to accomplish?
The obvious solution is to create a two-dimensional array of characters, then store the string in the array, one per row. Consider the following example:
char arr[][ 6 ] = { "123", "456", "X123", "X456" };
Note that we are allowed to omit the number of rows in the arr array, but C requires that we specify the number of columns. Unfortunately, not all the strings are long enough to fill an entire row of the array, so C padded them with null characters. ( Note that there is a bit of wasted space in the array )
0 1 2 3 4 5
+-----+-----+-----+-----+-----+-----+
0 | 1 | 2 | 3 | '\0'| '\0'| '\0'|
+-----+-----+-----+-----+-----+-----+
1 | 4 | 5 | 6 | '\0'| '\0'| '\0'|
+-----+-----+-----+-----+-----+-----+
2 | X | 1 | 2 | 3 | '\0'| '\0'|
+-----+-----+-----+-----+-----+-----+
3 | X | 4 | 5 | 6 | '\0'| '\0'|
+-----+-----+-----+-----+-----+-----+
If having three stars in your code is what you want, then you will have to add one additional element which is always NULL. ( By the way, why don't you want to use the length of the array? )
Another way is to use a ragged array. C doesn't provide a "ragged array type", but it does give us the tools to simulate one. ( just create an array whose elements are pointers to strings ) Consider the following example:
#define N 4
int main( int argc, const char * argv[] ) {
char *str[] = { "123", "456", "X123", "X456" };
for ( char **p = &str[ 0 ]; p < str + N; ++p ) {
puts( *p );
}
return EXIT_SUCCESS;
}
To access one of the strings, all we need is subscript the arr array.
Hope this helps..
It is hard to tell what you are attempting to do, but if I understand correctly, you appear to have an additional array dimension that isn't required. You are testing an uninitialized value as soon as you reach the 5th string (leading to your segfault). To correct it, you could do something like:
#include <stdio.h>
void f(char **array){
while (*array != '\0'){
// while (*array != '\0'){
printf("%s\n",*array);array++;
//}
}
}
int main(){
char *arr[50]={"123","456","X123","X456",NULL};
f(arr);
return 0;
}
Output
$ ./bin/func_f
123
456
X123
X456
Note: an explicit NULL is used as a sentinel to stop iterating when the data is exhausted. There are a number of ways to handle this, this being only one.
You generally shouldn't use pointers and arrays interchangeably. The common knowledge is that they're the same, but they aren't. This is particularly true for multi-dimensional arrays.
Multidimensional arrays have to be laid out linearly in memory, since addresses are linear. There are a couple ways to do this, but C uses row-major ordering. What this means is that the last index increases fastest as addresses increase.
For example, a two dimensional array
int x[rows][cols];
the two statements would be equivalent
x[row][col] = y;
*(x + (row * cols) + col) = y;
What this means is that in order to access the elements of your multi-dimensional array in a function, the function needs to know at least the sizes of the higher dimensions to validly access.
void f(int rows, int cols, char* array[rows][cols]){
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%s\n", array[i][j]);
}
}
}
int main(){
char* arr[50][50]={{"123","456"},{"X123","X456"}};
f(50, 50, arr);
return 0;
}
However, if it is necessary to iterate without knowing the dimensions, you can take advantage of the memory layout to effectively iterate over rows and columns (and higher dimensions). Although, this adds the necessity for an entry in the array that signals an end (e.g. NULL). Aside from making the code more complex, it adds memory overhead since the last row containing the NULL generally must be allocated.
#include <stdio.h>
void f(char** array){
while (*array)
printf("%s\n", *(array++));
}
int main(){
char* arr[][2] = { {"123","456"}, {"X123","X456"}, {NULL, NULL} };
f((char**) arr);
return 0;
}

Resources