What is the error in this c code - c

main() {
char names [5][20] = {
"rmaesh",
"ram",
"suresh",
"sam"
"ramu"
};
char *t;
t = names[2];
names[2] = names[3];
names[3] = t;
printf(" the array elemsnt are \n");
int i = 0;
for (i = 0; i < 5; i ++)
printf("\n%s", names[i]);
}
i am getting below error while compiling this program
stringarrary.c: In function ‘main’:
stringarrary.c:12:11: error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’
names[2] = names[3];
^
stringarrary.c:13:11: error: incompatible types when assigning to type ‘char[20]’ from type ‘char *’
names[3] = t;

It is illegal to try and assign to an array. In this case you should use the strcpy function. Note that your char *t; idea does not work either if you intend to swap the two arrays, because it only points at one of your existing strings; as soon as you write over names[2], that data is gone.
char t[20];
strcpy(t, names[2]);
strcpy(names[2], names[3]);
strcpy(names[3], t);
Also, "\n%s" should be "%s\n" - you want the newline to come after what you printed. And don't forget to #include <stdio.h> and #include <string.h>.

The error on line 13 is easiest to understand: names[3] is an array of char; you can't just assign a pointer to it. On line 12, the compiler is converting names[3] to a pointer and trying to assign it to the array names[2], which is likewise can't do.
Try copying the strings instead. In C, you can't copy arrays using the = operator; use the functions from memcpy or strcpy families.

The names array is a two-dimensional array of characters. As the other answers have pointed out, when you want to copy an array of characters, you need to use memcpy or strcpy.
The alternative solution is to make names a one-dimensional array of pointers. The resulting code would look like this.
int main( void )
{
char *names[5] = {
"rmaesh",
"ram",
"suresh",
"sam",
"ramu"
};
char *t;
t = names[2];
names[2] = names[3];
names[3] = t;
printf(" the array elemsnt are \n");
int i = 0;
for (i = 0; i < 5; i ++)
printf("\n%s", names[i]);
}
The advantage to this method is that it allows you to manipulate the pointers the way you wanted to. The disadvantage is that the strings are read-only. Attempting to modify the strings will result in undefined behavior.

Try this
#include<stdio.h>
#include <string.h>
main() {
char names [5][20] = {
"rmaesh",
"ram",
"suresh",
"sam", //<----- You are missing this (,) at the end
"ramu"
};
char *t;
strcpy( t, names[2]); // And also use this syntax
strcpy(names[2] , names[3]);
strcpy(names[3], t);
printf(" the array elemsnt are \n");
int i = 0;
for (i = 0; i < 5; i ++)
printf("\n%s", names[i]);
}

Related

How to reverse every string in an array of strings through a function in C?

I have been trying to solve this issue for whole day, and could not do it on my own. Searching the internet didn't help me solve it either
So, this the function prototype:
void invert(char **arr, int n);
First argument is an array of strings, and the second one is number of strings in an array.
This is my code:
#include <stdio.h>
#include <string.h>
void invert(char** arr, int n)
{
int i, j, len;
for(j=0;j<n;j++)
{
len=strlen(arr[j]);
for(i=0;i<len/2;i++)
{
char tmp = arr[j][i];
arr[j][i] = arr[j][len - i - 1];
arr[j][len - i - 1] = tmp;
}
}
}
int main()
{
int n=3, i;
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
invert(arr, n);
for(i=0;i<3;i++)
{
printf("%s ",arr[i]);
}
}
The code breaks when it reaches the line:
arr[j][i] = arr[j][len - i - 1];
and I can't figure out why.
The function receives an array of strings perfectly (tested it with some printf statements for characters of specific strings), and the char tmp succesfully recieves a correct character, but the program crashed when it reaches the line mentioned earlier. Printf statements after that line don't work.
Did I miss anything? Can someone explain what am I doing wrong? Thank you!
For starters this code snippet
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
invokes undefined behavior because the pointer arr is uninitialized and has an indeterminate value.
Moreover this approach in any case is wrong because you may not change string literals.
What you need is to declare a two-dimensional array as for example
enum { N = 11 };
//...
char arr[3][N] =
{
"John", "Doe", "Programmer"
};
In this case the function declaration will look like
void invert( char arr[][N], int n );
The enumeration must be declared before the function declaration.
Instead of the two-dimensional array you could declare an array of pointers like
char s1[] = "John";
char s2[] = "Doe";
char s3[] = "Programmer";
char * arr[3] = { s1, s2, s3 };
In this case the function declaration may be as shown in your question
void invert(char** arr, int n)
So what you need to do with minimal changes is to substitute this code snippet
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
for this code snippet
char s1[] = "John";
char s2[] = "Doe";
char s3[] = "Programmer";
char * arr[3] = { s1, s2, s3 };
To begin with, what you have here:
char **arr;
is a pointer to pointer to char.
Secondly, even if you had an array of pointers to char, like so :
char *arr[3];
And then assigning each string literal :
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
would still invoke Undefined behavior, since you are attempting to modify a string literal which is read only.
What you need is, either a 2D array of chars :
char arr[][100] = {"John", "Doe", "Programmer"};
and also change the function signature to :
void invert(char arr[][100], int n)
or you have to dynamically allocate memory and use a function like strcpy(), strdup(), memcpy() etc :
char **arr;
arr = malloc(n * sizeof(char *)); // or sizeof(*arr)
if (arr == NULL) {
fprintf(stderr, "Malloc failed to allocate memory\n");
exit(1);
}
arr[0] = strdup("John"); // good idea to also check if strdup returned null
arr[1] = strdup("Doe");
arr[2] = strdup("Programmer");
invert(arr, n);
for(i=0;i<3;i++)
{
printf("%s ",arr[i]);
}
for (i = 0; i < 3; i++) {
free(arr[i]);
}
free(arr);

How to call and pass array of string and find the length of that array inside the function

I am writing a program to check if a string is inside an array of strings.
I predefined an array of words before the main method
const char *items[] = {"a","b","c","d"};
then I have a function like
bool isInside(const char *array[], char *s1){
//which will try to compare all strings from the input array with s1
int len = sizeof(array)/sizeof(array[0]);
for (int i =0; i< len ; i++){
//do string comparasion}
}
It worked before but not sure where I messed up the code now I got two errors and the function is only able to check the first string of the array with s1.
I found out the problem is that now len = 1 always.
one of the errors is
`warning: ‘sizeof’ on array function parameter ‘array’ will return size of ‘const char **’ [-Wsizeof-array-argument]` and the other one is
isInside(items, words[i]))
| ^~~~~~~~~
| |
| const char **
code.c:63:21: note: expected ‘char *’ but argument is of type ‘const char **’
How can I fix this or call this function so the length is correct and no type warning?
Thanks a lot.
Arrays in C will degrade to pointers when passed as arguments to functions. When they become pointers, their length cannot be retrieved by sizeof.
You should pass the length of arrays as an additional argument to the function.
Maybe your function can be modified as:
bool isInside(const char **array, int arrayLength, char *s1){
for (int i =0; i< arrayLength; i++){
const char* str = array[i];
if(strcmp(str, s1) == 0){
return 1;
}
}
return 0;
}

Function printing list of words

I'm trying to understand what is wrong here.
void longestConsec(char* strarr[], int n) {
for(int i=0; i<n; i++)
{
printf("%s\n",strarr[i]);
}
}
int main()
{
char string[8][14] = {"zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"};
longestConsec(string, 8);
return 0;
}
I want to print every single word, and for some reason it doesn't work. What I think of is that strarr is array of pointer to char, so in every cell there should be a word, right? But when i tried to debug the code i saw that strarr and strarr[0] have different memory locations. Why?
strarr is an array of pointers to char, but string is not an array of pointers but an array of 14-element array of chars.
Pointers and 14-element array of chars may have different size, so your code won't work well.
How about using array of pointers like this?
#include <stdio.h>
void longestConsec(const char* strarr[], int n) {
for(int i=0; i<n; i++)
{
printf("%s\n",strarr[i]);
}
}
int main()
{
const char* string[8] = {"zone", "abigail", "theta", "form", "libe", "zas", "theta", "abigail"};
longestConsec(string, 8);
return 0;
}
Your compiler should have given you a warning that gives a good hint.
k.c:12:19: warning: passing argument 1 of ‘longestConsec’ from incompatible pointer type [-Wincompatible-pointer-types]
12 | longestConsec(string, 8);
| ^~~~~~
| |
| char (*)[14]
k.c:2:26: note: expected ‘char **’ but argument is of type ‘char (*)[14]’
2 | void longestConsec(char* strarr[], int n) {
| ~~~~~~^~~~~~~~
string is an array of arrays, char[8][14] and strarr is a pointer to pointer to char, char **. When string is passed to the function it decays to pointer to array of 14 char, char (*)[14]. Passing multidimensional arrays to functions can be tricky, but this works:
// size_t is better than int in this case
void longestConsec(size_t len, char strarr[][len], size_t n)
{
for(int i=0; i<n; i++)
printf("%s\n",strarr[i]);
}
And then call it with:
longestConsec(sizeof string[0]/sizeof string[0][0], // 14
string,
sizeof string/sizeof string[0] // 8
);
Note that you can write sizeof string[0] instead of sizeof string[0]/sizeof string[0][0] but that's because sizeof char is always 1.
Understanding these declarations can be a bit tricky. Just to give a type example of how they are declared:
char (*arr)[10]; // arr is a pointer to array of char of size 10
char *arr[10]; // arr is an array of 10 pointers to char
Related: arrays are not pointers and pointers are not arrays

How to properly convert an array string of 'numbers', using a cipher of letters?

I'll get to the point. I know this should be simple, but is giving me the runaround.
I am working on a secure local network. I need to take an input (in my case, an IP address) And cipher that address before storing it safely in a database.
I'd like to cipher it into a letter format. Hard to explain, but if you view this code, you should see what I'm trying to accomplish. I've formatted it to accept an input from you, the user, whereas this function will be called in real time in the background when it's working properly.
Ideally, the user would input 12.23.34.45
The function would print KS.SL.LE.EI
#include <stdio.h>
#include <string.h>
#define MAXLEN 16
void cwitch(char *instr[MAXLEN]){
char *nstr = "0123456789";
char *cstr = "DKSLEIANQP";
int count = strlen(instr);
char *output[count];
int i;
for(i = 0; i < count; i++){
if(instr[i] != '\0'){
int t;
for(t = 0; t < count; t++){
if(instr[i] == "."){ /*Do Nothing, Straight Logic - I Know This Is Useless*/ }
else if(instr[i] == nstr[t]) output[i] = cstr[t];
}
}
}
output[count] = 0; //Null Terminate The String
printf("Output: %s\n", output);
}
int main(void){
char *input[500];
printf("Enter Address: ");
fgets(input, sizeof(input), stdin);
input[strlen(input) - 1] = 0; //Remove \newline Character
cwitch(input);
return 0;
}
However, upon execution, I'm clearly not getting the desired results, or I wouldn't be here!
[root#RyM ~]# ./test
Enter Address: 12.23.34.45
Output:
`
[root#RyM ~]# ./test
Enter Address: 167.174.12.178
Output:
[root#RyM ~]# ./test
Enter Address: 45.223.6.1
Output:
`
[root#RyM ~]# ./test
Enter Address: 918.6.56.222
Output:
[root#RyM ~]#
Any help/advice is appreciated. I'm new into C. Expect warnings when compiling this. Feel free to roast/advise me, pertaining to said warnings existence.
Edit: Warnings included below
[root#RyM ~]# gcc -o test Test.c
Test.c: In function ‘cwitch’:
Test.c:10: warning: passing argument 1 of ‘strlen’ from incompatible pointer type
/usr/include/string.h:399: note: expected ‘const char *’ but argument is of type ‘char **’
Test.c:19: warning: comparison between pointer and integer
Test.c:19: warning: assignment makes pointer from integer without a cast
Test.c: In function ‘main’:
Test.c:31: warning: passing argument 1 of ‘fgets’ from incompatible pointer type
/usr/include/stdio.h:626: note: expected ‘char * __restrict__’ but argument is of type ‘char **’
Test.c:32: warning: passing argument 1 of ‘strlen’ from incompatible pointer type
/usr/include/string.h:399: note: expected ‘const char *’ but argument is of type ‘char **’```
The main problem in your code is a wrong definition of char array (or const string).
A correct definition would be:
char output[count]; // where count is compile time constant
and NOT char *output[count];
the [] tells the compiler this is an array (which is a type of pointer).
Thus, no need to use *, unless you want to define an array of pointers (which is not your case).
here is a cleaned-up code: * Note: this code is far from being perfect or even good, I merely made small changes in order to make it compile and work. *
#include <stdio.h>
#include <string.h>
#define MAXLEN 16
void cwitch(const char* instr) {
const char* nstr = "0123456789";
const char* cstr = "DKSLEIANQK";
int count = strlen(instr);
char output[MAXLEN];
int i;
for (i = 0; i < count; i++) {
if (instr[i] != '\0') {
int t;
for (t = 0; t < count; t++) {
if (instr[i] == '.') {
output[i] = '.';
}
else if (instr[i] == nstr[t]) output[i] = cstr[t];
}
}
}
output[count] = 0; //Null Terminate The String
printf("Output: %s\n", output);
}
int main(void) {
char input[500];
printf("Enter Address: ");
fgets(input, sizeof(input), stdin);
input[strlen(input) - 1] = 0; //Remove \newline Character
cwitch(input);
return 0;
}
In this line
void cwitch(char *instr[MAXLEN])
you are saying that cwitch accepts an array of character pointers (of MAXLEN length). It should just be char *instr. Similar, in this line
char *output[count];
you are declaring an array of char *, while you intend it to be an array of char: char output[count]. Finally, you cannot compare a character 'x' to a string
if (instr[i] == ".")
-- it must be a character literal again ('.').
A small logic problem: if the input character is . you must not "do nothing", you must copy it to the output string as well.
With these fixes your program actually works.

Passing an array of pointers to strings into a function

I am trying to pass an array of pointers to strings (names) into a function (foo) and read from it. The below code produces a segmentation fault. Can someone please help me figure out why this code is resulting in a segmentation fault? I want to be able to pass the array names[][] through a function and work with the data like I would if I were using names[][] outside the function.
void foo(char *bar[]) {
printf("%s\n", bar[0]);
}
//---------------Main-------------
char args[][50] = {"quick", "brown", "10", "brown", "jumps", "5"};
int i = 0;
int numbOfPoints = (sizeof(args)/sizeof(args[0]))/3;
//array of all the locations. the number will be its ID (the number spot in the array)
//the contents will be
char names[numbOfPoints][100];
for(i = 0; i < numbOfPoints; i++) {
char *leadNode = args[i*3];
char *endNode = args[i*3 + 1];
char *length = args[i*3 + 2];
int a = stringToInt(length);
//add name
strcpy(names[i],leadNode);
}
//printing all the names out
for(i = 0; i < numbOfPoints; i++) {
printf("%s\n", names[i]);
}
foo(names);
The problem is the the argument type of foo and the way you are calling it. The argument type of foo, char* [] is not compatible with name. I get the following warning in gcc 4.8.2 with -Wall.
soc.c:35:4: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
foo(names);
^
soc.c:5:6: note: expected ‘char **’ but argument is of type ‘char (*)[100]’
void foo(char *bar[]) {
Change foo to:
void foo(char (*bar)[100]) {
printf("%s\n", bar[0]);
}
and all should be well.

Resources