Copying strings into an array? - c

#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)

Related

C program for how to reverse a number explanation needed

While searching for a C program on how to reverse a string, i came across the below program. I am already familiar with a program where we take the length of the string and then minus each character and find the reverse. But this a different program. So can someone please tell me how this code works? Help will be gratefully accepted.
compiler used is Borland Turbo c.
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main() {
char str[50];
char rev[50];
int i, j, n;
clrscr();
printf("enter the string to be reversed:");
scanf("%s", &str);
for (i = 0; str[i] != 0; i++) {
n = i - 1;
}
for (j = 0; j <= i - 1; j++) {
rev[j] = str[i];
n--;
}
printf("the reverse of the string is:%s", rev);
getch();
}
In C, strings are NUL-terminated meaning that it has '\0' at the end signifying the end of the string. The code you've posted currently has two issues:
This:
scanf("%s", &str);
should be
scanf("%s", str);
as %s expects a char*, not a char(*)[50].
This:
rev[j] = str[i];
should be
rev[j] = str[n];
rev should be NUL-terminated before printing. Add
rev[j] = '\0';
just before
printf("the reverse of the string is:%s", rev);
to avoid Undefined Behavior.
Your code doesn't work as it is supposed to.Have you tried it ?
Consider this approach to reverse a string :
#include <stdio.h>
#include <string.h>
int reverse(char *Str);
void swap(char *x, char *y);
int main(int argc, char *argv[]) {
char Str[255];
printf("enter the string to be reversed : ");
scanf("%s", Str);
reverse(Str);
printf("the reverse of the string is : %s\n", Str);
}
int reverse(char *Str) {
size_t len = strlen(Str);
size_t n = len / 2;
char *begin = Str;
char *end = (Str + len) - 1;
while (n > 0) {
swap(begin, end);
begin++;
end--;
n--;
}
return 0;
}
void swap(char *x, char *y) {
char tmp;
tmp = *x;
*x = *y;
*y = tmp;
}

Using an array of pointers?

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.

qsort function is causing issues

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.

Run-Time Check Failure #2 - Stack around the variable 'command' was corrupted

I'm getting this error while running the code above:
#include <stdio.h>
#include <stdlib.h>
int ln(char *str);
int compare(char *str1, char *str2);
void reverse(char *str, int n);
void main(){
int n;
int len;
char *str;
char command[2];
printf("Enter your string:\n");
scanf("%d", &n);
str = malloc(n);
scanf("%s", str);
printf(">");
scanf("%s", command);
if (compare(command, "ln")) {
len = ln(str);
printf("%d\n", len);
}
if (compare(command, "rv")) {
reverse(str, n);
printf("The current string is %s\n", str);
}
free(str);
}
int ln(char *str) {
int i = 0;
while (str[i] != '\0') {
i++;
}
return i;
}
int compare(char *str1, char *str2) {
int i = 0;
while (str1[i] == str2[i] && str1[i] != '\0' && str2[i] != '\0') {
i++;
}
if (str1[i] == '\0' && str2[i] == '\0') {
return 1;
}
else {
return 0;
}
}
void reverse(char *str, int n){
int i;
for (i = 0; i < n / 2; i++){
char tmp = str[i];
str[i] = str[n - 1 - i];
str[n - i - 1] = tmp;
}
}
I've searched online, but any related error I've read about was about writing to much to the allocated memory and such things.
The error happens when I enter the values "5 abcde" or "4 abcd" or any other number & string (the number equals the string length), and the "rv" (reverse) command.
While debugging, I found that the code works perfectly, and the error appears only at the last line (after the string has been reversed).
Any help would be appriciated!
char command[2]; declares a buffer of length 2. So it can contain a string of length 1 at most because you need one char more for the zero terminator.
As soon as you enter a string longer than 1 during scanf("%s", command); you will get a buffer overflow which corrupts the stack, hence the error.
Reserve a longer buffer for example with char command[200];
EDIT
Other problem:
Instead of reverse(str, n); use reverse(str, ln(str)); . n contains the maximum string length used fot malloc and the reverse function wants the actual string length in the second parameter.

How to remove the character at a given index from a string in C?

How do I remove a character from a string?
If I have the string "abcdef" and I want to remove "b" how do I do that?
Removing the first character is easy with this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[] = "abcdef";
char word2[10];
strcpy(word2, &word[1]);
printf("%s\n", word2);
return 0;
}
and
strncpy(word2, word, strlen(word) - 1);
will give me the string without the last character, but I still didn't figure out how to remove a char in the middle of a string.
memmove can handle overlapping areas, I would try something like that (not tested, maybe +-1 issue)
char word[] = "abcdef";
int idxToDel = 2;
memmove(&word[idxToDel], &word[idxToDel + 1], strlen(word) - idxToDel);
Before: "abcdef"
After: "abdef"
Try this :
void removeChar(char *str, char garbage) {
char *src, *dst;
for (src = dst = str; *src != '\0'; src++) {
*dst = *src;
if (*dst != garbage) dst++;
}
*dst = '\0';
}
Test program:
int main(void) {
char* str = malloc(strlen("abcdef")+1);
strcpy(str, "abcdef");
removeChar(str, 'b');
printf("%s", str);
free(str);
return 0;
}
Result:
>>acdef
My way to remove all specified chars:
void RemoveChars(char *s, char c)
{
int writer = 0, reader = 0;
while (s[reader])
{
if (s[reader]!=c)
{
s[writer++] = s[reader];
}
reader++;
}
s[writer]=0;
}
char a[]="string";
int toBeRemoved=2;
memmove(&a[toBeRemoved],&a[toBeRemoved+1],strlen(a)-toBeRemoved);
puts(a);
Try this . memmove will overlap it.
Tested.
Really surprised this hasn't been posted before.
strcpy(&str[idx_to_delete], &str[idx_to_delete + 1]);
Pretty efficient and simple. strcpy uses memmove on most implementations.
int chartoremove = 1;
strncpy(word2, word, chartoremove);
strncpy(((char*)word2)+chartoremove, ((char*)word)+chartoremove+1,
strlen(word)-1-chartoremove);
Ugly as hell
The following will extends the problem a bit by removing from the first string argument any character that occurs in the second string argument.
/*
* delete one character from a string
*/
static void
_strdelchr( char *s, size_t i, size_t *a, size_t *b)
{
size_t j;
if( *a == *b)
*a = i - 1;
else
for( j = *b + 1; j < i; j++)
s[++(*a)] = s[j];
*b = i;
}
/*
* delete all occurrences of characters in search from s
* returns nr. of deleted characters
*/
size_t
strdelstr( char *s, const char *search)
{
size_t l = strlen(s);
size_t n = strlen(search);
size_t i;
size_t a = 0;
size_t b = 0;
for( i = 0; i < l; i++)
if( memchr( search, s[i], n))
_strdelchr( s, i, &a, &b);
_strdelchr( s, l, &a, &b);
s[++a] = '\0';
return l - a;
}
This is an example of removing vowels from a string
#include <stdio.h>
#include <string.h>
void lower_str_and_remove_vowel(int sz, char str[])
{
for(int i = 0; i < sz; i++)
{
str[i] = tolower(str[i]);
if(str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u')
{
for(int j = i; j < sz; j++)
{
str[j] = str[j + 1];
}
sz--;
i--;
}
}
}
int main(void)
{
char str[101];
gets(str);
int sz = strlen(str);// size of string
lower_str_and_remove_vowel(sz, str);
puts(str);
}
Input:
tour
Output:
tr
Use strcat() to concatenate strings.
But strcat() doesn't allow overlapping so you'd need to create a new string to hold the output.
I tried with strncpy() and snprintf().
int ridx = 1;
strncpy(word2,word,ridx);
snprintf(word2+ridx,10-ridx,"%s",&word[ridx+1]);
Another solution, using memmove() along with index() and sizeof():
char buf[100] = "abcdef";
char remove = 'b';
char* c;
if ((c = index(buf, remove)) != NULL) {
size_t len_left = sizeof(buf) - (c+1-buf);
memmove(c, c+1, len_left);
}
buf[] now contains "acdef"
This might be one of the fastest ones, if you pass the index:
void removeChar(char *str, unsigned int index) {
char *src;
for (src = str+index; *src != '\0'; *src = *(src+1),++src) ;
*src = '\0';
}
This code will delete all characters that you enter from string
#include <stdio.h>
#include <string.h>
#define SIZE 1000
char *erase_c(char *p, int ch)
{
char *ptr;
while (ptr = strchr(p, ch))
strcpy(ptr, ptr + 1);
return p;
}
int main()
{
char str[SIZE];
int ch;
printf("Enter a string\n");
gets(str);
printf("Enter the character to delete\n");
ch = getchar();
erase_c(str, ch);
puts(str);
return 0;
}
input
a man, a plan, a canal Panama
output
A mn, pln, cnl, Pnm!
Edit : Updated the code zstring_remove_chr() according to the latest version of the library.
From a BSD licensed string processing library for C, called zString
https://github.com/fnoyanisi/zString
Function to remove a character
int zstring_search_chr(char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
/* validate input */
if (!(str && bad))
return NULL;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
Exmaple Usage
char s[]="this is a trial string to test the function.";
char *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
void dele_char(char s[],char ch)
{
int i,j;
for(i=0;s[i]!='\0';i++)
{
if(s[i]==ch)
{
for(j=i;s[j]!='\0';j++)
s[j]=s[j+1];
i--;
}
}
}
int main()
{
char s[MAX],ch;
printf("Enter the string\n");
gets(s);
printf("Enter The char to be deleted\n");
scanf("%c",&ch);
dele_char(s,ch);
printf("After Deletion:= %s\n",s);
return 0;
}
#include <stdio.h>
#include <string.h>
int main(){
char ch[15],ch1[15];
int i;
gets(ch); // the original string
for (i=0;i<strlen(ch);i++){
while (ch[i]==ch[i+1]){
strncpy(ch1,ch,i+1); //ch1 contains all the characters up to and including x
ch1[i]='\0'; //removing x from ch1
strcpy(ch,&ch[i+1]); //(shrinking ch) removing all the characters up to and including x from ch
strcat(ch1,ch); //rejoining both parts
strcpy(ch,ch1); //just wanna stay classy
}
}
puts(ch);
}
Let's suppose that x is the "symbol" of the character you want to remove
,my idea was to divide the string into 2 parts:
1st part will countain all the characters from the index 0 till (and including) the target character x.
2nd part countains all the characters after x (not including x)
Now all you have to do is to rejoin both parts.
This is what you may be looking for while counter is the index.
#include <stdio.h>
int main(){
char str[20];
int i,counter;
gets(str);
scanf("%d", &counter);
for (i= counter+1; str[i]!='\0'; i++){
str[i-1]=str[i];
}
str[i-1]=0;
puts(str);
return 0;
}
I know that the question is very old, but I will leave my implementation here:
char *ft_strdelchr(const char *str,char c)
{
int i;
int j;
char *s;
char *newstr;
i = 0;
j = 0;
// cast to char* to be able to modify, bc the param is const
// you guys can remove this and change the param too
s = (char*)str;
// malloc the new string with the necessary length.
// obs: strcountchr returns int number of c(haracters) inside s(tring)
if (!(newstr = malloc(ft_strlen(s) - ft_strcountchr(s, c) + 1 * sizeof(char))))
return (NULL);
while (s[i])
{
if (s[i] != c)
{
newstr[j] = s[i];
j++;
}
i++;
}
return (newstr);
}
just throw to a new string the characters that are not equal to the character you want to remove.
Following should do it :
#include <stdio.h>
#include <string.h>
int main (int argc, char const* argv[])
{
char word[] = "abcde";
int i;
int len = strlen(word);
int rem = 1;
/* remove rem'th char from word */
for (i = rem; i < len - 1; i++) word[i] = word[i + 1];
if (i < len) word[i] = '\0';
printf("%s\n", word);
return 0;
}
This is a pretty basic way to do it:
void remove_character(char *string, int index) {
for (index; *(string + index) != '\0'; index++) {
*(string + index) = *(string + index + 1);
}
}
I am amazed none of the answers posted in more than 10 years mention this:
copying the string without the last byte with strncpy(word2, word, strlen(word)-1); is incorrect: the null terminator will not be set at word2[strlen(word) - 1]. Furthermore, this code would cause a crash if word is an empty string (which does not have a last character).
The function strncpy is not a good candidate for this problem. As a matter of fact, it is not recommended for any problem because it does not set a null terminator in the destination array if the n argument is less of equal to the source string length.
Here is a simple generic solution to copy a string while removing the character at offset pos, that does not assume pos to be a valid offset inside the string:
#include <stddef.h>
char *removeat_copy(char *dest, const char *src, size_t pos) {
size_t i;
for (i = 0; i < pos && src[i] != '\0'; i++) {
dest[i] = src[i];
}
for (; src[i] != '\0'; i++) {
dest[i] = src[i + 1];
}
dest[i] = '\0';
return dest;
}
This function also works if dest == src, but for removing the character in place in a modifiable string, use this more efficient version:
#include <stddef.h>
char *removeat_in_place(char *str, size_t pos) {
size_t i;
for (i = 0; i < pos && str[i] != '\0'; i++)
continue;
for (; str[i] != '\0'; i++)
str[i] = str[i + 1];
return str;
}
Finally, here are solutions using library functions:
#include <string.h>
char *removeat_copy(char *dest, const char *src, size_t pos) {
size_t len = strlen(src);
if (pos < len) {
memmove(dest, src, pos);
memmove(dest + pos, src + pos + 1, len - pos);
} else {
memmove(dest, src, len + 1);
}
return dest;
}
char *removeat_in_place(char *str, size_t pos) {
size_t len = strlen(str);
if (pos < len) {
memmove(str + pos, str + pos + 1, len - pos);
}
return str;
}
A convenient, simple and fast way to get rid of \0 is to copy the string without the last char (\0) with the help of strncpy instead of strcpy:
strncpy(newStrg,oldStrg,(strlen(oldStrg)-1));

Resources