return a modified array of char** - arrays

C- language——-Trying to call a function "test" from main(). This takes 3 arguments argc, argv and a pointer function which either turns the string into lower case or upper case. Then using the array of modified values i will just loop and print them.
I get segmentation fault error.
I want to return the entire array. So that in my main() i will loop through it and print it. How can i do this? Where am i going wrong in my code? Any help would be great.

Your codes have some incorrect points and are redundant as well.
You can try the below codes
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
char **test(int argc, const char *const *argv, int (*const chnge)(int)){
char **retArr = malloc((argc+1) * sizeof(char*));
for (int i = 0; i < argc; ++i) {
const char *str = argv[i];
int len = strlen(str);
char* transform = malloc((len+1) * sizeof(char));
for (int j = 0; j < (len+1); ++j) {
transform[j] = chnge(str[j]);
}
retArr[i] = transform;
}
retArr[argc] = NULL; // An array of char* terminated by NULL
return retArr;
}
int main(int argc, const char *const *argv) {
char **val1 = test(argc, argv, &toupper);
char **val2 = test(argc, argv, &tolower);
for (char *const *p = val1, *const *q = val2; *p && *q; ++argv, ++p, ++q) {
printf("[%s] -> [%s] [%s]\n", *argv, *p, *q);
free(*p);
free(*q);
}
free(val1);
free(val2);
}

I believe the answer may have to do with the fact that you are trying to directly act on a string 1. without using strcpy, and 2. using a pointer array (char*) instead of an array object (char[]) which can cause a segfault.
Sorry, this would better be suited to a comment and not an answer, but I unfortunately can't comment quite yet. This may be of help?

Related

Printf didn't display the first one, just after that ones

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* foo (const char* str)
{
char szo[125];
char* vege;
int i,j=0;
int db=1;
szo[0] = str[0];
for(i=1; i<strlen(str)+1; i++)
{
if(str[i] == str[i-1] )
{
db++;
}
else
{
j++;
szo[j] = db + '0';
j++;
szo[j] = str[i];
db=1;
}
}
j++;
szo[j] = '\0';
vege = szo;
return vege;
}
int main()
{
char *s[] = {"hello", "world", "Mississippi"};
int i;
for (i = 0; i < sizeof(s) / sizeof(char *); ++i)
{
char *p = foo(s[i]);
printf("%s\n", p);
}
return EXIT_SUCCESS;
}
I've tried to do first a printf("\n"), then its good, but i have a empty first line.
Someone can please help me.Thanks a lot.
Or if anyone can help me, the original tasks say a free(p) in the main after the printf, how can i change everything to work with malloc?
szo ceases to exist right before foo() returns.
Yet you return a pointer to that array and try to use it outside the function.
If you're not ever going to call foo recursively, or in parallel in several threads, or as different arguments of another function, try static char szo[125]; and remember to document that the function returns a pointer to a static array so that you don't invoke UB in 6 months time
char *foo(const char *str) {
static char szo[125];
//...
return szo;
}
printf("%s\n", foo("something")); //ok
printf("%s\n", foo("some other thing")); //ok
//printf("%s\n%s\n", foo("something"), foo("some other thing")); //NO
char* foo (const char* str)
{
char szo[125];
...
vege = szo;
return vege;
}
you return pointer to the local variable which does not exist after the return from the function. One of the most common UBs

imitate strcpy function in c using char pointers

I am try to write a user defined function which will do exactly what strcpy() library function do. But although there is no error, my program crashes and not copying second string to first string. What's wrong with this code and how to fix it?
#include<stdio.h>
#include<string.h>
int main(){
char *ch1="abcd";
char *ch2="efgh";
str_cpy(ch1,ch2);
}
str_cpy(char *c1,char *c2){
int i=0;
while(c1[i]!='\0'){
i++;
}
printf("%c",*(c1+3));
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
String literals are generally put into read only area, that's why the program crashed when you are writing into c1. The destination string needs to be an array or allocated buffer:
char c1[5];
str_cpy(c1, c2);
Also, in the function, it looks you are copying c2 to c1, but you are counting the length of c1, you should count the length of c2 instead:
// copy string c2 to c1
void str_cpy(char *c1, const char *c2){
int i=0;
while(c2[i]!='\0'){
i++;
}
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
Your program invokes undefined behavior because you are trying to write to a string literal. String literals can be stored in read only memory, which is probably the case on your system, hence causing a crash.
Note that your string copying function can perform the copy in a single loop:
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
You can verify the behavior with a modified main:
#include <stdio.h>
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
int main(void) {
char buf[20];
char *ch2 = "Hello world\n";
printf("%s\n", str_cpy(buf, ch2));
return 0;
}
Here is a possible rework of your code, which doesn't have to pre-define buffer size (c1). You simply pass the buffer address. Also, please note that such buffer has to be freed once used (for example, if declared in local scope, not in main()):
#include <stdio.h>
#include <stdlib.h>
char *str_cpy(char **c1, const char *c2) {
int i, size = 0;
for(i = 0; ; i++)
if(c2[i] == '\0')break;
size = i + 1;
if(!(*c1 = realloc(*c1,size*sizeof(char))))
return *c1;//or devise some more sophisticated error handling
for (i = 0;; i++) {
(*c1)[i] = c2[i];
if (c2[i] == '\0')
return *c1;
}
}
int main(void){
char *ch1 = malloc(1); //you're responsible for freeing it, once used
char *ch2 = "Hello, everybody in the neighborhood!";
printf("%s\n",str_cpy(&ch1,ch2));
free(ch1);
return 0;
}
Please, also note you don't need to #include <string.h>

Conflicting types for 'reverse_string' function

I was using this SO question as part of a program that needs to reverse a string. The problem I am having is that I cannot seem to get the function to work. Here is the code I have:
int main(int argc, char *argv[]){
char *test = "Testing";
fputs(test, stdout);
fputs(reverse_string(test), stdout);
}
char* reverse_string(char *str){
char temp;
size_t len = strlen(str) - 1;
size_t i;
size_t k = len;
for(i = 0; i < (len +1)/2; i++){
temp = str[k];
str[k] = str[i];
str[i] = temp;
k--;
}
return str;
}
I am getting an error that there is conflicting types for 'reverse_string'
Edit: For anyone wondering here is the code that works. See #chux's answer for an explanation.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* reverse_string(char *str){
char temp;
size_t len = strlen(str) - 1;
size_t i;
size_t k = len;
for(i = 0; i < (len +1)/2; i++){
temp = str[k];
str[k] = str[i];
str[i] = temp;
k--;
}
return str;
}
int main(int argc, char *argv[]){
char test[] = "Testing";
fputs(test, stdout);
fputs(reverse_string(test), stdout);
}
You can not pass a const char * to a char *
char *test = "Testing";
fputs(reverse_string(test), ... // bad, attempting to change constant data.
// bad as reverse_string() is assumed to return int, but fputs() expects char *
char* reverse_string(char *str) { // Bad, there's now a function conflict
Instead
char* reverse_string(char *str); // Need to declare/define function first
char test[] = "Testing";
fputs(reverse_string(test), ... // good
[Edit]
You problem was well identified (missing function declaration) by others. My suggestion takes care of the next problem. In C, a missing declaration of a function will assume int reverse_string(...) which does not match char* reverse_string(char *str).
[Edit]
As #Shafik Yaghmou suggests, modifying a string literal char *test = "Testing" will result in undefined behavior. Hence the char test[] = "Testing" which initializes test with "Testing\0", but may be modified.
[Edit]
#GreenAsJade correctly points out OP's original error message is due to the assumed int reverse_string(...) supplying an int to s in int fputs(const char * s, FILE * stream);
char *test1 = "Testing" is not the same thing as char test2[] = "Testing". test1 becomes a char * with the size of a pointer. The initial pointer value is to a string "Testing" located elsewhere in memory. test2 is a char array with size 8: length of "Testing" + 1 for '\0'. The array test2 is initialized with 'T', 'e', ... '\0' etc.
FWIW:
(h2hh)momerath:Documents mgregory$ cat test.c
char* reverse_string(char *str) {
return str;
}
char *test = "Testing";
int main() {
reverse_string(test);
}
(h2hh)momerath:Documents mgregory$ gcc test.c
(h2hh)momerath:Documents mgregory$
I think that the answer to the OP's question is that reverse_string has to be declared before being used, to be not int.

Dynamic and static char array

Here are the codes of a program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * cloning(char * q){
char s[strlen(q)];
int i;
for(i = 0; i < strlen(q); i++)
s[i] = q[i];
return s;
}
int main(){
char q[] = "hello";
char *s = cloning(q);
return 0;
}
After the compilation a warning appears, so I changed the returned value like this:
char *b = s;
return b;
In this way the warning can be solved. However I found that inside the function cloning(), sizeof(s) is 5, but strlen(s) is 7. And if I change char s[strlen(q)] simply to char s[5], the output is still incorrect. Can anybody explain this problem to me? Thank you very much.
char s[strlen(q)] is a local variable, and hence when you return its address, it results in undefined behaviour. Thus either you could use strdup() or malloc() to dynamically allocate the array, thus ensuring that the array s is available on the heap when you return from the function. The returned array would need to be free()-ed as well, else it would have a memory leak :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * cloning(char * q){
char *s = malloc(strlen(q)+1);
// if you write char s[strlen(q)], it is defined locally, and thus on return gives an undefined behaviour
int i;
for(i = 0; i < strlen(q)+1; i++)
s[i] = q[i];
return s;
}
int main(){
char q[] = "hello";
char *s = cloning(q);
free(s);
return 0;
}
char s[strlen(q)];
is a variable-length array. Like a malloc'ed buffer its size is determined at runtime. Unlike a malloc'ed buffer, it ceases to exist when the function returns.
multiple issues with this code:
char * cloning(char * q){
char s[strlen(q)]; // s has strlen size but needs strlen + 1 to hold \0
int i;
for(i = 0; i < strlen(q); i++) // should copy the \0 otherwise q is not a valid string
s[i] = q[i];
return s;// returns the address of a local var == undef. behavior
}
if you want to clone a string just do strdup()
char* cloning(char* q)
{
return strdup(q);
}
or the equivalent
char * cloning(char * q)
{
char* s = malloc(strlen(q)+1);
int i;
for(i = 0; i < strlen(q)+1; i++)
s[i] = q[i];
return s;
}
The proper way to do this with standard C, no matter version of the C standard, is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* cloning (const char* str)
{
char* clone;
size_t size = strlen(str) + 1;
clone = malloc(size);
if(clone == NULL)
{
return NULL;
}
memcpy(clone, str, size);
return clone;
}
int main(){
char original[] = "hello";
char* clone = cloning(original);
if(clone == NULL)
{
puts("Heap allocation failed.");
return 0;
}
puts(clone);
free(clone);
return 0;
}
Dynamic arrays in C are declared using Malloc and Calloc. Try googling it.
Eg:
char *test;
test = (char *)malloc(sizeof(char)*Multiply_By);
In C,static array is in stack,after function return,it's been destoryed. and string with char has a '\0' end. But strlen don't include it. For example.char q[] = "hello"; strlen(q) = 5,but the real size is 6
If you want to copy a string, the last '\0' must be added at the end.or using
char *s = malloc(sizeof(q)); ...; for(i = 0; i < sizeof(q); i++)
s[i] = q[i];
you also need to free it after using.Maybe become a mem leak.
Hope this can help u.

Null terminating char pointer

I am completely newbie in C.
I am trying to do simple C function that will split string (char array).
The following code doesn't work properly because I don't know how to terminate char array in the array. There are to char pointers passed in function. One containing original constant char array to be split and other pointer is multidimensional array that will store each split part in separate char array.
Doing the function I encountered obviously lots of hustle, mainly due to my lack of C experience.
I think what I cannot achieve in this function is terminating individual array with '\0'.
Here is the code:
void splitNameCode(char *code, char *output);
void splitNameCode(char *code, char *output){
int OS = 0; //output string number
int loop;
size_t s = 1;
for (loop = 0; code[loop]; loop++){
if (code[loop] == ':'){
output[OS] = '\0'; // I want to terminate each array in the array
OS ++;
}else {
if (!output[OS]) {
strncpy(&output[OS], &code[loop], s);
}else {
strncat(&output[OS], &code[loop], s);
}
}
}
}
int main (int argc, const char * argv[]) {
char output[3][15];
char str[] = "andy:james:john:amy";
splitNameCode(str, *output);
for (int loop = 0; loop<4; loop++) {
printf("%s\n", output[loop]);
}
return 0;
}
Here is a working program for you. Let me know if you need any explanation.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void splitNameCode(char *code, char **output) {
int i = 0;
char* token = strtok(code, ":");
while (token != NULL) {
output[i++] = token;
token = strtok(NULL, ":");
}
}
int main (int argc, const char *argv[]) {
char* output[4];
char input[] = "andy:james:john:amy";
splitNameCode(input, output);
for (int i = 0; i < 4; i++) {
printf("%s\n", output[i]);
}
return 0;
}
If I understand your intent correctly, you are trying to take a string like andy:james:john:amy and arrive at andy\0james\0john\0amy. If this is the case, then your code can be simplified significantly:
void splitNameCode(char *code, char *output){
int loop;
strncpy(code, output, strlen(code));
for (loop = 0; output[loop]; loop++){
if (output[loop] == ':'){
output[loop] = '\0'; // I want to terminate each array in the array
}
}
}

Resources