What is wrong with my program reversing strings in C? - c

I want to create a function to reverse a string in C. I found a couple pre-made on the internet but I wish to create mine. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* inverseCarac(char* chaine){
if(chaine==0||*chaine==0) return NULL;
int j, i;
int taille=strlen(chaine);
char* inverse=malloc(taille*sizeof(char));
for(j=taille-1, i=0; j>0; j--, i++){
*(inverse+i)=*(chaine-j);
}
return inverse;
}
int main(void){
char* test="bonjour";
char* inv=inverseCarac(test);
printf("%s", inv);
return 0;
}
I can't figure out why I get a segmentation fault.

There were several errors in your code, the most significant being the offset from chaine in the wrong direction. Also, lack of space for a string terminator, and j ending prematurely.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* inverseCarac(char* chaine){
if(chaine==0||*chaine==0) return NULL;
int j, i;
int taille=strlen(chaine);
char* inverse=malloc(taille+1); // add 1 for terminator
for(j=taille-1, i=0; j>=0; j--, i++){ // change j>0 to j >= 0
*(inverse+i)=*(chaine+j); // change -j to +j
}
inverse[taille] = '\0'; // write terminator
return inverse;
}
int main(void){
char* test="bonjour";
char* inv=inverseCarac(test);
printf("%s\n", inv);
return 0;
}
Program output
ruojnob

Related

Argument type void is incomplete?

My program is supposed to convert a string to lowercase but I keep gettingg this error "Argument type void is incomplete" when trying to convert a string to lowercase and I don't know why. Could anyone explain why this is happening, thanks
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char str[25] ="HELLOWORLD";
void upperToLower(char *str){
for (size_t i = 0; i < strlen(str); ++i) {
printf("%c", tolower((unsigned char) str[i]));
}
}
int main(void) {
upperToLower(str);
printf("%s\n", upperToLower(str));
return 0;
}
OUTPUT
I guess upperToLower is supposed to modify the string in place. Try the following code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char str[25] ="HELLOWORLD";
void upperToLower(char *str){
for (size_t i = 0; i < strlen(str); ++i) {
str[i] = tolower((unsigned char) str[i]);
}
}
int main(void) {
upperToLower(str);
printf("%s\n", str);
return 0;
}
You could also make upperToLower return the pointer that was passed to it (like strcpy does with its first parameter). That allows the the upperToLower call to be done as part of the printf call like this:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char str[25] ="HELLOWORLD";
char *upperToLower(char *str){
for (size_t i = 0; i < strlen(str); ++i) {
str[i] = tolower((unsigned char) str[i]);
}
return str;
}
int main(void) {
printf("%s\n", upperToLower(str));
return 0;
}
The return type of the function upperToLower() is void, so it cannot be used as a value in expressions.
The function upperToLower() prints things inside that, so you won't need to externally print something about that except for the newline character.
Try this:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char str[25] ="HELLOWORLD";
void upperToLower(char *str){
for (size_t i = 0; i < strlen(str); ++i) {
printf("%c", tolower((unsigned char) str[i]));
}
}
int main(void) {
upperToLower(str);
upperToLower(str); /* put this out of printf() */
printf("\n"); /* and print just newline character here */
return 0;
}
Yes. As specified in C specification the type void is an incomplete type.
The void type comprises an empty set of values; it is an incomplete
object type that
cannot be completed.
As result it is not possible to form any value of type void. Pointers of type void* can be used, but they cannot be dereferenced.
Your function returns void, you're literally passing nothing as a parameter.

Storing user-inputted strings into a string array in c?

Fairly new to C, I am trying to read a file of multiple words using bash indirection, and put the words into a string array. The end of the file is marked with a -1.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void init(char* words[]);
int main(int argc,char *argv[]){
char* words[400000];
init(words);
int i = 0;
do{
printf("%s",words[i]);
i++;
}while(!strcmp(words[i],"-1"));
}
void init(char* words[]){ // initializes array
int i = 0;
do{
fgets(words[i],1024,stdin);
i++;
}while(!strcmp(words[i],"-1"));
}
This gives me a segmentation fault, if any other information is needed I'm more than happy to provide it.
If I guessed correctly, '400000' means the max lines the user can input. But the default size of stack on Windows OS is 1M, sizeof(void*) * 400000 = 1,600,000...
The other thing is that you have not allocated memory for every line.
So, I try to correct your code like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE 4000 // '400000' is really too big!
void init(char* words[]);
int main(int argc,char *argv[]){
char* words[MAX_LINE];
memset(words, 0 , sizeof(words));
init(words);
int i = 0;
do{
printf("%s",words[i]);
delete words[i];
words[i] = nullptr;
i++;
}while(!strcmp(words[i],"-1"));
}
void init(char* words[]){ // initializes array
int maxLen = 1024;
int i = 0;
do{
words[i] = new char[maxLen];
memset(words[i], 0, maxLen);
fgets(words[i], maxLen, stdin);
i++;
}while(!strcmp(words[i],"-1") && i < MAX_LINE);
}

Randomize letters in string in C

I have for example "asd" and I want it to be randomized to DAS, DSA, SAD, you know. How can I code this? Tried a few solutions but It didnt really work.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
int main()
{
printf("type in the word\n");
char haslo[128];
scanf("%s", haslo);
char set[128];
char hasloa[128];
strcpy(set, haslo);
unsigned int Ind = 0;
srand(time(NULL) + rand());
int len = strlen(set);
while(Ind < len)
{
hasloa[Ind++] = set[rand()%62];
}
hasloa[len] = '\0';
printf("%s", hasloa);
return 0;
}
Change 62 inside the while loop to "len"

Debugger shows wrong value to pointer

I have the following code:
#include <iostream>
#include <cstdio>
#include <list>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <limits>
#include <functional>
#include <algorithm>
#include <cmath>
#include <string>
#include <ostream>
#include <sstream>
#include <bitset>
#include <numeric>
#include<fstream>
using namespace std;
char str[] = "this.is.a.test";
char str2[] = "this.is.another.test";
typedef struct
{
size_t count;
char** strings;
} Tokens;
Tokens Tokenize(char* String, char Split)
{
Tokens t;
t.count = 1;
for (size_t i = 0; String[i] != 0; i++)
{
if (String[i] == Split)
t.count++;
}
t.strings =(char**) malloc(sizeof(char*)* t.count);
if (t.count > 0)
t.strings[0] = String;
for (size_t i = 0, j = 1; String[i] != 0; i++)
{
if (String[i] == Split)
{
t.strings[j] = &String[i + 1];
String[i] = 0;
j++;
}
}
return t;
}
int main(void)
{
Tokens t = Tokenize(str, '.');
printf("number of strings: %i\n---\n", t.count);
for (size_t i = 0; i < t.count; i++)
{
printf("%i: %s\n", i, t.strings[i]);
}
free(t.strings);
}
The problem is when I debug the code and especially that line t.strings[j] = &String[i + 1];
In a test case of this.is.a.test
At the first found dot . , it should points to this, but in the debugger it shows the following picture.
enter code here
What the debugger shows is correct at line 55. The assignment has been made, so t.strings[j] points after the dot.
Note that in Tokenize you allocate Tokens t; on the stack and later return this t. That is bad (very bad!). Because t is on the stack, it will be overwritten by the call to printf.
(And although most is C, formally it is C++ as in C you cannot declare a variable in the for initialization, as in for (size_t i = 0;)

Wrong result when copying an array of strings

I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
char* passwd;
int nr;
void test()
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
for (i=0; i<argc; i++)
{
user=strdup(argv[i]);
}
test();
return 0;
}
The result is the argv[argc] on all the positions. How can I fix this? I wwant to have that test() outside the loop.
**
EDIT
**
After the ANSWERS here this is my new code, which is not working. Can anyone say why?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
void test(int n)
{
int i=0;
for(i=0;i<n;i++)
printf("%s \n",user[i]);
}
int main(int argc,char*argv[])
{
user = (char*) malloc(argc*sizeof(char));
int i;
for (i=0;i<argc;i++)
{
user[i]=argv[i];
}
test(argc);
return 0;
}
You are assigning to both password and user at each iteration of the for loop. The final values you see are from the last iteration. Also, there is memory leak due to overwriting the pointers from previous strdup calls. In fact, you do not need a loop:
int main(int argc,char*argv[])
{
if(argc == 3) {
user=strdup(argv[1]);
passwd=strdup(argv[2]);
} else {
// error: usage
}
test();
return 0;
}
If you want to have multiple user/password combinations:
char *user[256], *passwd[256];
void test(int n) {
int i;
for(i=0;i<n;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
for(i = 0; i < argc && i < 256; i+=2) {
user[i]=strdup(argv[i]);
passwd[i]=strdup(argv[i+1]);
}
test(argc);
return 0;
}
Because you overwrite the pointers user and passwd in every iteration. Hence, you'll only see the last string.
If you can tell your aim of the program, a better answer can be provided. Because I am not sure whether you want to read one user and passwd Or an array of users and passwds.
After you edit, I see you want to read an array of strings:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** user;
// or char *user[100]; /* If you want a fix length array of pointers. Now, you dont have to malloc. /*
char* passwd;
int nr;
void test(int argc)
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
user = malloc(argc*sizeof(char*));
for (i=0; i<argc; i++)
{
user[i]=strdup(argv[i]);
}
test(argc);
return 0;
}
Of course; in test() you don't use i other than a loop variable and in main() you keep overwriting the previous value of user and passwd. In effect, what you do is:
user = strdup(argv[0]); /* Note: argv[0] is the program name. */
passwd = strdup(argv[0]);
user = strdup(argv[1]);
passwd = strdup(argv[1]);
user = strdup(argv[2]);
passwd = strdup(argv[2]);
user = strdup(argv[3]);
passwd = strdup(argv[3]);
printf("%s %s \n", user, passwd);
With this information, can you fix your program?
$ cat trash.c
#include <stdio.h>
#include <string.h>
void test(FILE* stream, char* usr, char* pass) {
fprintf( stream, "%s#%s\n", usr, pass);
}
int main(int argc, char** argv) {
int i = 1;
if (argc % 2) {
while(argv[i]) {
test(stdout, argv[i], argv[i + 1]);
i += 2;
}
}
return 0;
}
$ clang trash.c
$ ./a.out user1 pass1 user2 pass2
user1#pass1
user2#pass2
$
also if you call strdup() don't forget to free memory, because strdup called malloc().

Resources