When I compile this code as it is, I get this error:
variable-sized object 'word_list' may not be initialized
char *word_list[i] = malloc(sizeof(char) * STRING_LENGTH );
I know on line 13 my variable word_list is just a pointer to characters and that it is causing the problem. I have to use an array of pointers instead of it but I am not sure how to do this properly. The word_list variable is supposed to be an array that is to have strings copied into it using strcpy.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define STRING_LENGTH 20
#define MAX 30
int read_string(char string[], int n);
int compare(const void*a, const void*b);
int main(){
int i;
char* word_list;
char word[STRING_LENGTH + 1];
for (i = 0; ; i++){
printf("\nEnter a word.\n");
read_string(word, STRING_LENGTH);
if (word[0] == '\0')
break;
char *word_list[i] = malloc(sizeof(char) * STRING_LENGTH );
free(word_list);
strcpy(word_list[i], word);
}
int length = sizeof(word_list)/sizeof(char*);
int j;
for (j = 0; word_list[j] != '\0'; j++)
printf("%s\n", word_list[j]);
qsort(word,length, sizeof(char*), compare);
for (j = 0; word_list[j] != '\0'; j++)
printf("%s\n", word_list[j]);
return 0;
}
int compare(const void*element1, const void *element2){
const char *string1 = *(const char**)element1;
const char *string2 = *(const char**)element2;
return strcmp(string1,string2);
}
int read_string(char string[], int n){
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
string[i++] = ch;
string[i] = '\0';
return i;
}
So if I am understanding correctly, you want an array of strings? (note this is just an array of pointers and you still need to malloc the space for each individual string)
So
char *word_list[NUM_STRINGS];
word_list[i] = malloc(strlen(word) + 1);
strcpy(word_list[i], word);
But it looks like all elements in your array will be the same length? In which case you can just use something like this, without the need for malloc or free:
char word_list[NUM_STRINGS][STRING_LENGTH+1];
strcpy(word_list[i], word);
If you're looking to have it loop indefinitely while their is user input then you won't be able to accomplish this easily with an array (only if you care about them going over the NUM_STRINGS limit). A linked list would work better in my opinion.
You declared word_list as a character pointer, not an array of same. If your malloc is intended to allocate space for one of the elements of an array, you need to create the array first. (The line with the error looks like you are declaring a variable.)
If you know how big this array needs to be, you should be all set. But if you don't, you might want to look into how realloc works.
Related
#include<stdio.h>
#include<conio.h> //**Just To Add getch() function**
int length(char *p){
int i; //**I know That these variable are not the same as they are in other function**
for(i=0;*(p+i)!='\0';i++);
return i;
}
void strrev(char *p){
int i,len;
len=length(p);
char cpy[len]; //**Already Tried to change it to some fixed value**
for(i=0;i<len;i++){
cpy[i]=*(p+len-i);
}
for(i=0;i<len;i++){
*(p+i)=cpy[i];
}
}
int main(){
char str[20]="computer";
strrev(str);
printf("%s",str);
getch(); //**to Stop The Screen**
return 0;
}
I have tried changing the array size to a fixed value i also tried with changing the variable but there is no mistake in my syntax.
By recommendation of #Yunnosch, here is my comment as an answer.
In your function strrev you iterate over the whole string i.e. the iterations for i from zero to len / 2 you correctly grab the characters, but the remaining iterations just undo this again.
Thus, just iterate from zero to len >> 1. The bit-shift ensures integer division.
void strrev(char* const str)
{
const size_t len = strlen(str);
for(size_t i = 0; i < (len >> 1u); ++i)
{
const size_t j = len - 1u - i;
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
using this cpy[i]=*(p+len-i); means you are placing \0 terminator in the beginning of string cpy. in which case your both of strings will start with \0 and so printf will do nothing.
so change cpy[i]=*(p+len-i); to cpy[i] = *(p + len - i-1);.
I have this function which receives a pointer to char array and initializes it to be len repetitions of "a":
void test(char ** s, int len) {
*s = (char *)malloc(sizeof(char) * len);
int i;
for(i = 0; i < len; i++) {
*(s[i]) = 'a';
}
printf("%s\n", *s);
}
in the main() I have this code:
char * s;
test(&s, 3);
but I get EXC_BAD_ACCESS (code=1, address=0x0) error when I run main(). The error occurs on the second iteration of the for loop in this line: *(s[i]) = 'a';
As far as I understand I'm not accessing the elements correctly, what is the correct way?
s is declared as a pointer to a pointer. In reality, it's a pointer to a pointer to the start of an array, but that cannot be inferred from the type system alone. It could just as well be a pointer to a start of an array of pointers, which is how s[i] treats it. You need to first derefence s (to get the pointer to the array's start), and then index on it:
(*s)[i] = 'a';
Also, as #MFisherKDX correctly pointed out in comments, if you're going to pass *s to printf or any other standard string-manipulation function, you have to turn into a proper C string by terminating it with a 0 character.
This more clearly shows what you should be doing, while staying close to your original code:
void test(char ** s, int len) {
char *p = malloc(len);
int i;
for(i = 0; i < len; i++) {
p[i] = 'a';
}
printf("%s\n", p);
*s = p;
}
Note that sizeof(char) is always one by definition, and in C there's no need to cast the result of malloc().
That code also has all your original problems in that it doesn't actually create a string that you can send to printf( "%s... ). This fixes that problem:
void test(char ** s, int len) {
char *p = malloc(len+1);
int i;
for(i = 0; i < len; i++) {
p[i] = 'a';
}
p[i]='\0';
printf("%s\n", p);
*s = p;
}
And this is even easier, with no need to use a double-* pointer:
char *test(int len) {
char *p = malloc(len+1);
int i;
for(i = 0; i < len; i++) {
p[i] = 'a';
}
p[i]='\0';
printf("%s\n", p);
return(p);
}
Instead of assignment
*(s[i]) = 'a';
use this:
(*s)[i] = 'a';
But do not forget that C/C++ strings are null terminated
Or you can use this approach to get more readable code:
void test(char** s, int len) {
// 1 char extra for zero
char *str = (char*)malloc(sizeof(char) * (len+1));
int i;
for(i = 0; i < len; i++)
str[i] = 'a';
// zero terminated string
str[len] = 0;
printf("%s\n", str);
*s = str;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define STRING_LENGTH 20
#define MAX 30
int read_string(char string[], int n);
int main(){
int i = 0;
char *name_list[MAX];
char word[STRING_LENGTH + 1];
for (;; i++){
printf("Enter a word.\n");
read_string(word, STRING_LENGTH);
if (word[i] == '\0')
break;
name_list[i] = malloc(sizeof(char) * 20);
strcat(name_list[i], word);
}
}
int read_string(char string[], int n){
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
string[i++] = ch;
string[i] = '\0';
return i;
}
The point of this program is to read in words and place them into an array of pointers for sorting. this is what i have so far, my debugger is saying that the use of strcat is unsafe but I do not know why. It says to use strcat_s but that crashes my program. Any help on how to get this working?
Ok, I tested your code and I came to the following final code that is working for me and does not give me a warning when compiled with -Wall.
Since you are using strcat instead of strcpy, the string stored in words gets added to the data in the array name_list. But because you didn't put all values in that array to 0, it could happen some garbage data is stored in name_list[i] and the words string gets concatenated after that garbage data.
Therefore I used calloc so all values in the memory you allocate are zero. Another way is to just keep malloc but then change strcat() in strcpy().
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define STRING_LENGTH 20
#define MAX 30
int read_string(char string[], int n);
int main(){
int i;
char *name_list[MAX];
char word[STRING_LENGTH + 1];
for (i = 0; i < MAX; i++){
printf("\nEnter a word.\n");
read_string(word, STRING_LENGTH);
printf("\nword%d=%s", i, word);
if (strcmp(word, "") == 0)
break;
name_list[i] = calloc(STRING_LENGTH + 1, 1);
strcat(name_list[i], word);
printf("\nname_list[%d] = %s", i, name_list[i]);
}
return 0;
}
int read_string(char string[], int n){
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
string[i++] = ch;
string[i] = '\0';
return i;
}
Use the memcpy() function :
void *memcpy(void *str1, const void *str2, size_t n)
or the strcpy() function :
char *strcpy(char *dest, const char *src)
here is my code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define STRING_LENGTH 20
#define MAX 30
int read_string(char string[], int n);
int compare(const void*a, const void*b);
int main(){
int i;
char* word_list[30];
char word[STRING_LENGTH + 1];
for (i = 0; ; i++){
printf("\nEnter a word.\n");
read_string(word, STRING_LENGTH);
if (word[0] == '\0')
break;
word_list[i] = (char *)malloc(STRING_LENGTH + 1);
//free(word_list);
strcpy(word_list[i], word);
}
int length = sizeof(word_list)/sizeof(char*);
int j;
qsort(word,length, sizeof(char*), compare);
for (j = 0; word_list[j] != '\0'; j++)
printf("%s\n", word_list[j]);
return 0;
}
int compare(const void*element1, const void *element2){
const char *string1 = *(const char**)element1;
const char *string2 = *(const char**)element2;
return strcmp(string1,string2);
}
int read_string(char string[], int n){
int ch, i = 0;
while ((ch = getchar()) != '\n')
if (i < n)
string[i++] = ch;
string[i] = '\0';
return i;
}
My program is supposed to read in strings via the read_string function and then strcpy is used to place them as elements of an array of pointers, then the names are sorted alphabetically. It compiles and reads i my input but it crashes once it gets to qsort(). I know qsort() is causing the problem but I don't know why. Any help would be very appreciated.
There are a number of issues as pointed out in the comments. The primary being you are calling qsort with the incorrect pointer, and incorrect number of members (30) instead of the number of strings read. A correction would be:
qsort (word_list, i, sizeof (char *), compare);
While you can use a sentinel to stop the print after qsort completes, why? You already know how many strings you read in i. So simply:
for (j = 0; j < i; j++)
printf ("%s\n", word_list[j]);
As an aside, it would be useful to be able to stop input after any number of strings in read_string. Allowing for an keyboard generated EOF to signal end of input by ctrl+d (ctrl+z on windows) will work. E.g.:
while ((ch = getchar ()) != '\n' && ch != EOF)
Notice that it is word_list and not word you would like to sort.
int main() {
int i;
char* word_list[30];
char word[STRING_LENGTH + 1];
for(i = 0; ; i++) {
printf("\nEnter a word.\n");
read_string(word, STRING_LENGTH);
if(word[0] == '\0')
break;
word_list[i] = (char *)malloc(STRING_LENGTH + 1);
strcpy(word_list[i], word);
}
// call qsort with the number of items in the wordlist
qsort(word_list, i, sizeof(char*), compare);
}
int compare(const void*element1, const void *element2){
const char **string1 = (const char**)element1;
const char **string2 = (const char**)element2;
return strcmp(*string1,*string2);
}
You should also call set length to the number of items in word_list before calling qsort() not to the number of characters in a word.
For instance if you have read in two words from stdin then you call qsort() like this qsort(word_list, 2, sizeof(char*), compare);
Perhaps I also need to mention that you should free the memory allocated by malloc() when you have finished using the word list.
I am new with pointers on C and I am trying to write a function like strcat() but without using it. I developed the following function:
char cat(char *a, char *b) {
int i=0,cont=0,h=strlen(a)+strlen(b);
char c[h]; //new string containing the 2 strings (a and b)
for(i;i<strlen(a);++i) {
c[i] = *(a+i); //now c contains a
}
int j = i;
for(j;j<strlen(b);++j) {
c[j] = *(b+cont); //now c contains a + b
cont++;
}
return c; // I return c
}
And this is how I call the function:
printf("\Concatenazione: %c", cat(A,B));
It is now working because the final result is a weird character. How could I fix the function? Here there's the full main.
char * strcat(char *dest, const char *src)
{
int i;
int j;
for (i = 0; dest[i] != '\0'; i++);
for (j = 0; src[j] != '\0'; j++) {
dest[i+j] = src[j];
}
dest[i+j] = '\0';
return dest;
}
From your implementation it appears that your version of strcat is not compatible with the standard one, because you are looking to allocate memory for the result, rather than expecting the caller to provide you with enough memory to fit the result of concatenation.
There are several issues with your code:
You need to return char*, not char
You need to allocate memory dynamically with malloc; you cannot return a locally allocated array.
You need to add 1 for the null terminator
You need to write the null terminator into the result
You can take both parameters as const char*
You can simplify your function by using pointers instead of indexes, but that part is optional.
Here is how you can do the fixes:
char *cat(const char *a, const char *b) {
int i=0,cont=0,h=strlen(a)+strlen(b);
char *c = malloc(h+1);
// your implementation goes here
c[cont] = '\0';
return c;
}
You are returning a POINTER to the string, not the actual string itself. You need to change the return type to something like "char *" (or something equivalent). You also need to make sure to null terminate the string (append a '\0') for it to print correctly.
Taking my own advice (and also finding the other bug, which is the fact that the second for loop isn't looping over the correct indices), you end up with the following program:
#include <stdio.h>
char *cat(char *a, char *b) {
int i = 0, j = 0;
int cont = 0;
int h = strlen(a) + strlen(b) + 1;
char *result = (char*)malloc(h * sizeof(char));
for(i = 0; i < strlen(a); i++) {
result[i] = a[i];
}
for(j = i; j < strlen(b)+ strlen(a); j++) {
result[j] = b[cont++];
}
// append null character
result[h - 1] = '\0';
return result;
}
int main() {
const char *firstString = "Test First String. ";
const char *secondString = "Another String Here.";
char *combined = cat(firstString, secondString);
printf("%s", combined);
free(combined);
return 0;
}
c is a local variable. It only exists inside the function cat. You should use malloc.
instead of
char c[h];
use
char *c = malloc(h);
Also, you should add the null byte at the end. Remember, the strings in C are null-ended.
h = strlen(a) + strlen(b) + 1;
and at the end:
c[h - 1] = '\0';
The signature of cat should be char *cat(char *a, char *b);
You will get an error of
expected constant expression
for the code line char c[h];. Instead you should be using malloc to allocate any dynamic memory at run-time like::
char* c ;
c = malloc( h + 1 ) ; // +1 for the terminating null char
// do stuff
free( c ) ;
Your corrected code::
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include <stdlib.h>
char* cat(char *a, char *b) {
int i=0,cont=0,h=strlen(a)+strlen(b), j;
char *c;
c = malloc( h+1 ) ;
for(i;i<strlen(a);++i) {
c[i] = *(a+i);
}
j = 0 ;
for(j;j<strlen(b);++j) {
c[i] = *(b+cont);
i++ ;
cont++;
}
c[i] = 0 ;
return c;
}
int main() {
char A[1000],B[1000];
char * a ;
printf("Inserisci la stringa 1: \n");
gets(A);
printf("Inserisci la stringa 2: \n");
gets(B);
a = cat(A,B) ;
printf("\nConcatenazione: %s", a);
free(a) ;
getch();
return 0;
}