Copy strings with limited characters - c

Alright this is a homework question whereby I can't use the string.h library. This function is to copy not more than n characters (characters that
follow a null character are not copied) from the array pointed to by s2 to the array pointed to by s1.
int main()
{
char sourceString[100];
char targetString[100];
int num;
printf("Enter a string:");
gets(sourceString);
printf("Enter no. of characters: ");
scanf("%d", &num);
printf("stringncpy(): %s", stringncpy(targetString, sourceString, num));
}
char *stringncpy(char * s1, char * s2, int n)
{
int i;
for (i = 0; i < n; i++)
{
if (s2[i] != '\0')
{
s1[i] = s2[i];
}
else
{
break;
}
}
s1[i] = '\0';
return s1;
}
It runs fine except that it is printing some rubbish unrecognizable characters after n characters. Apprantly running the code with http://ideone.com/, I don't get those rubbish characters but on VS it does.

Because gets is used it is better to use
if (s2[i] != '\0' && s2 [i] != '\n')
instead if
if (s2[i] != '\0')
And if n define the max numer of character you should ensure that n < 100. When after for loop i == n writing '\0' to i-th position can cause a problem. Or maybe loop should be
for (i = 0; i < n-1; i++)

Related

Same first and last letter in array C

My assignment is to write a C program, in which user inputs a sentence, and the program checks if there are words that begin and end with the same letter (for example eye, roar, sos etc.)
I wrote this and I am not sure it will work
I've also got an error: uninitialized local variable 'p2' used. May someone say where I should initialize it?
Maybe someone can add some tips for improving?
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
#define MAX 100
int main()
{
system("chcp 1251");
char arr[MAX];
char* p1, *p2;
int sym, i;
printf("\n\t Enter your sentence(use .(dot) or Enter to finish input):");
while ((sym = getchar()) != '.' && sym != '\n' && i < MAX)
{
arr[i++] = sym; //symbols to array
arr[i] = '0';
}
p1 = arr; //pointer for 1st symbol
for (i = 0; i < MAX; i++)
{
if (arr[i] == ',' || arr[i] == ' ') //finding a word
{
*p2 = arr[i--];
if (*p1 = *p2) //if first and last letters are equal
{
printf("%s", arr);
}
if (arr[i++] == ',' || arr[i++] == ' ')
{
*p1 = arr[i + 2];
}
*p1 = arr[i++];
}
}
return 0;
}```
The variable i should be initialized, i = 0; otherwise i starts from some random value. You can just use fgets to read input, then use strcspn to remove the last \n character.
*p2 = arr[i--];
p2 is declared as a pointer and again is not initialized. It's pointing to some random address in memory and should not be dereferenced yet.
If you are not experienced enough with pointers, you can just use the array style indexing.
for (i = 0; i < MAX; i++)...
MAX is the maximum number of characters which can be stored in arr. But string's length can be less, it's determined by strlen. Example:
char arr[MAX];
printf("input:");
fgets(arr, sizeof(arr), stdin);
arr[strcspn(arr, "\n")] = 0;
size_t len = strlen(arr);
if(len == 0) return 0;
if (arr[0] == arr[len - 1])
printf("first and last match");
else
printf("first and last don't match");
If there are more than one word in arr, you can use strtok to break arr in to words, check each word individually.

Trying to remove characters of string B from string A in standard C

So if A="aBcDeFg" and B="BDF", the output should be "aceg".
My idea was to check one-by-one if character of A is equal with any character of B (A[0] vs B[0]/B[1]...B[n] and so on). Therefore if they do not match, a counter variable is incremented. If the counter is smaller than length of B, then this character is deleted and when the counter equals length of B, the character is moved in an other string.
My version looks like this, but is not working:
void remove_characters(char s[], char r[])
{
int k, i, j, l = 0;
char s_copy[20];
for (i = 0; s[i] != '\0'; i++){
for (j = 0; r[j] != '\0'; j++)
if (s[i] != r[j])
k++;
if (k = strlen(r)){
s_copy[l++] = s[i];
k = 0;
}
}
puts(s_copy);
}
void main()
{
char s1[20],s2[20];
printf("Enter the first string: ");
gets(s1);
printf("Enter the second string: ");
gets(s2);
remove_characters(s1,s2);
}
Any ideas where is the problem?
Any ideas where is the problem?
There's more than one.
UnholySheep mentioned if (k = strlen(r)); you meant == rather than =.
k is not initialized before use; this is to be done before the inner loop.
s_copy is not null terminated.
Here's an alternative implementation which utilizes the standard function strchr and modifies s, which has the advantages that no limit is imposed on the length of s and that the result is available to the caller rather than just printed:
void remove_characters(char s[], char r[])
{
char *t = s;
do if (*s && strchr(r, *s)) continue;
else *t++ = *s;
while (*s++);
}

comparing a char to a string in C

I'm quite new to C and I'm wondering why in the code below, the char I'm comparing to each letter of the string word is showing that it's equal everytime.
For example
If I've inputted the word
apple
and I'm looking for any repeating char in "apple" my function. I pass in to the function each char of apple such as a, p, p etc. It should return 1 when I pass in p since it's repeated, but instead, for every char of apple, my function says a == word[0], a == word[1] even though word[1] for "apple" is 'p'.
I know char is ASCII, so each char has a number value, but I'm not sure why this is not working. Perhaps, I'm using the pointer *word in the functions arguments incorrectly?
My code is below for my function, rpt_letter:
int rpt_letter(char *word, char c)
{
int i;
int count = 0;
i = 0;
printf("This is the WORD %s\n", word);
while(count < 2)
{
if(word[i] == c)
{
count++;
printf("the count is %d\n the char is %c and the string is %c\n", count, c, word[i]);
}
i++;
}
if (count<2)
{
// printf("letter %c was not found in the array. \n", c);
return 0;
}
else
{
//printf("letter %c was found at index %d in the array.\n", c, mid);
repeats[rpt_counter] = c;
rpt_counter++;
return 1;
}
return 0;
}
I'll include the main method just in case -- but I believe the main method is working well
int main(void)
{
//! showArray(list, cursors=[ia, ib, mid])
//int n = 51;
char word[51];
scanf("%s", word);
//length of string
for (n=0; word[n] != '\0'; n++); //calculate length of String
printf("Length of the string: %i\n", n);
int count = 0;
//sort words
int i;
char swap = ' ';
for(int k = 0; k < n; k++)
{
for (i=0; i<n-1; i++)
{
//if prev char bigger then next char
if (word[i] > word[i+1])
{
//make swap = prev char
swap = word[i];
//switch prev char with next char
word[i] = word[i+1];
//make next letter char
word[i+1] = swap;
}
}
}
printf("%s\n", word);
for (i=0; i<n-1; i++)
{
int rpt = rpt_letter(word, word[i]);
if(rpt == 1)
{
count++;
}
}
printf("%d", count);
return 0;
}
I've tried a number of things such as using the operator !=, also <, > but it gives me the same result that each word[ia] == c.
You are getting this issue because in your code rpt_letter() the while loop has a terminating condition count >= 2. Now consider input apple and character a. As a appears in apple only once, the count after traversing the whole word remains 1. But the loop doesn't terminate. So, the index i becomes greater than the length of string and tries to check the character appearing after that.
The loop terminates eventually when it gets another a this way. You need to add a check for the terminating null character in your loop so that it doesn't cross the length of the string .
Change the while loop condition to something like -
while((count < 2) && (word[i] != '\0'))

Kochan InsertString segmentation fault

I am working through Kochan's programming in C book and I am working on an exercise which requires a function to insert one character string inside another string, with the function call including where the string is to be inserted.
I have written the below code but I receive a segmentation fault whenever I enter the inputs. I think it's because the 'input' string is defined to the length of the user's input and then the insertString function tries to add additional characters to this string. I just can't see a way of defining the string as large enough to be able to take in additional characters. Do you think that this is the reason I am receiving a segmentation fault? Are there any other ways to go about this problem?
#include<stdio.h>
#include <string.h>
insertString(char input[], const char insert[], int position)
{
int i, j;
char temp[81];
j = strlen(input);
for(i = 0; i < position - 1; i++)
{
temp[i] = input[i];
}
for(j = 0; insert != '\0'; i++, j++)
{
temp[i] = insert[j];
}
for(j = i - j; input != '\0'; i++, j++)
{
temp[i] = input[j];
}
for(i = 0; temp[i] != '\0'; i++)
{
input[i] = temp[i];
}
input[i] = '\0';
}
void readLine(char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
i++;
}
while(character != '\n');
buffer[i - 1] = '\0';
}
int main(void)
{
char input[81];
char insert[81];
int position;
printf("Enter the first string: ");
readLine(input);
printf("Enter the insert string: ");
readLine(insert);
printf("Enter placement position int: ");
scanf("%i", &position);
insertString(input, insert, position);
printf("The adjusted string is %s\n", input);
return 0;
}
There might be other reasons as well, but the following fragment will crash for sure:
for(j = 0; insert != '\0'; i++, j++)
{
temp[i] = insert[j];
}
The reason is that - since insert will not be increased or manipulated - this is an endless loop writing "indefinitely" long into temp. Once exceeding its length 80 (or a bit later) it will crash. I suppose you meant for(j = 0; insert[j] != '\0'; i++, j++), right?
Check all for loop conditions in insertString function. For example:
for(j = 0; insert != '\0'; i++, j++)
{
temp[i] = insert[j];
}
is infinite loop. Because of it you access memory out of temp array bounds. It causes UB and segmentation fault. Looks like you need insert[j] != '\0' condition here.
I'm familiar with this book. The author, Stephen Kochan, has a website with answers to the odd-numbered end of chapter exercises.
The website is at classroomm.com but you'll need to look around some to find the information.
Here is the info from that site related to this exercise:
Programming in C, exercise 10-7 (3rd edition) and 9-7 (4th edition)
/* insert string s into string source starting at i
This function uses the stringLength function defined
in the chapter.
Note: this function assumes source is big enough
to store the inserted string (dangerous!) */
void insertString (char source[], char s[], int i)
{
int j, lenS, lenSource;
/* first, find out how big the two strings are */
lenSource = stringLength (source);
lenS = stringLength (s);
/* sanity check here -- note that i == lenSource
effectively concatenates s onto the end of source */
if (i > lenSource)
return;
/* now we have to move the characters in source
down from the insertion point to make room for s.
Note that we copy the string starting from the end
to avoid overwriting characters in source.
We also copy the terminating null (j starts at lenS)
as well since the final result must be null-terminated */
for ( j = lenSource; j >= i; --j )
source [lenS + j] = source [j];
/* we've made room, now copy s into source at the
insertion point */
for ( j = 0; j < lenS; ++j )
source [j + i] = s[j];
}
There's an error somewhere in your insertString function where it goes out of bounds. By the way your insertString function doesn't start with the word void.
If I substitute the insertString function which I wrote for the exercise then the program works.
#include<stdio.h>
#include <string.h>
void insertString (char source[], const char s[], int start)
{
int stringLength (const char s[]);
int lenSource = strlen (source);
int lenString = strlen (s);
int i;
if ( start > lenSource ) {
printf ("insertion point exceeds string length\n");
return;
}
// move the characters in the source string which are above the
// starting point (including the terminating null character) to make
// room for the new characters; to avoid overwriting characters the
// process begins at the end of the string
for ( i = lenSource; i >= start; --i )
source[i + lenString] = source[i];
// insert new characters
for ( i = 0; i < lenString; ++i )
source[start + i] = s[i];
}
void readLine(char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
i++;
}
while(character != '\n');
buffer[i - 1] = '\0';
}
int main(void)
{
char input[81];
char insert[81];
int position;
printf("Enter the first string: ");
readLine(input);
printf("Enter the insert string: ");
readLine(insert);
printf("Enter placement position int: ");
scanf("%i", &position);
insertString(input, insert, position);
printf("The adjusted string is %s\n", input);
return 0;
}

Why isn't my program printing out the correct message?

I'm trying to write a program to see if string 1 is a part of string 2. At the command prompt, I enter string 1, and then string 2. But the problem is, no matter what I type, my program keeps printing out the answer that "No, string 1 is not a part of string 2". I'm not sure what I could be doing wrong, is there something wrong with my for loop? Help is appreciated!
int string_part_of_other(void)
{
char str1[20];
char str2[20];
int answer = 1;
printf("Enter string 1:\n");
scanf("%s", str1);
printf("Enter string 2:\n");
scanf("%s", str2);
for (int i = 0; str1[i] != '\0'; i++)
{
for (int j = 0; str2[j] != '\0'; j++)
{
if (str1[i] != str2[j])
{
answer = 0;
}
}
}
return answer;
}
int main()
{
int result;
result = string_part_of_other();
if (result == 1)
{
printf("Yes, string 1 is part of string 2.\n");
}
if (result == 0)
{
printf("No, string 1 is not part of string 2.\n");
}
return 0;
}
The problem is in your loop. You're comparing an entire string against one character.
for (int i = 0; str1[i] != '\0'; i++){
for (int j = 0; str2[j] != '\0'; j++){ // here
if (str1[i] != str2[j]) answer = 0;
}
}
strpbrk or strstr is a function that does this automatically, if that's what you would prefer.
You could also try this:
for (int i = 0; str1[i]; i++){
int j = 0;
for (; str2[j] && str1[i + j]; j++){
if (str2[j] != str1[i + j]) break;
}
if (!str2[j]) return 1; /*
* This means the loop broke because it reached the end of the
* string, not because of a mismatch. Therefore, str2 is within str1
*/
}
return 0;
Also, I think it is your intention to say string 2 is part of string 1, and not the other way around.
The algorithm you've written answers the following:
"For each character in string1, does it match every character in string2?"
If you step through the code in your head you should be able to figure out what's going wrong, and how to fix it.
For example, if your last char in str1 and last char in str2 do not match each other, the answer will be 0. Even if str2 is a part of str1
if (str1[i] != str2[j]) {
answer = 0;
}
If the 1st literal in your string1 does not match with string2 answer is set to 0, after that even if you find the substring you are not changing answer to 1 so you are not getting the proper result.
Also you are just incrementing str2 index and not incrementing str1 index with it, so you will never find the string, so change the logic.
Few remarks:
don't use scanf(). It doesn't do what you think it does, and it even goes unprotected without the ability to specify field width, so you should expect buffer overruns.
so use fgets(buf, sizeof(buf), stdin) instead (and beware of trailing newlines).
Don't reinvent the wheel: there's a function called strstr() in the C standard library which does exactly what you want, and it works correctly unlike your current ugly-hack-with-unreadable-nested-for-loops.
All in all:
int part_of()
{
char buf1[LINE_MAX], buf2[LINE_MAX], *p;
fgets(buf1, sizeof(buf1), stdin);
fgets(buf2, sizeof(buf2), stdin);
p = strchr(buf1, '\n');
if (p) *p = 0;
p = strchr(buf2, '\n');
if (p) *p = 0;
return strstr(buf1, buf2) != NULL;
}
Also, don't write if (func() == 1) {} then if (func() == 0) {} immediately afterwards - redundancy is bad. if (func()) {} else {} is fine.
you are just comparing all characters of str1 with that of str2 and even if one mismatch is there you set answer to zero .. wrong logic based on asked question
I am assuming you want to check str1 to be a part of str2, the outer loop should be of the parent or containing string in this case str2 ...
int answer=0;
for(int i=0;str2[i]!='\0';i++) //traversing bigger string
{
if(str2[i]==str1[0])
//if character of bigger string matches first character small string
{
for(int j=0;str1[j]!='\0';j++)
{
if(((i+j)<strlen(str2))&&(str1[j]!=str2[i+j])){
break;}
}//j
if(str1[j-1]=='\0')
{answer=1;
break;}
}//i
I rewrite some of your code:
#include <stdio.h>
int string_part_of_other(void)
{
char str1[20];
char str2[20];
int answer = 0;
int i, j, k;
printf("Enter string 1:\n");
scanf("%s", str1);
printf("Enter string 2:\n");
scanf("%s", str2);
i = j = k =0;
while(str2[j] !='\0')
{
k = j;
for(i = 0; str1[i] != '\0' && str2[k] != '\0'; i++, k++)
{
if(str1[i] != str2[k])
{
break;
}
}
if(str1[i] == '\0')
{
answer = 1;
}
j++;
}
return answer;
}
int main()
{
int result;
result = string_part_of_other();
if (result == 1)
{
printf("Yes, string 1 is part of string 2.\n");
}
if (result == 0)
{
printf("No, string 1 is not part of string 2.\n");
}
return 0;
}

Resources