I need to write a probram in C, which adds a string to a string etc. (for example '5' strings - It needs to read "vbvbvbvbvb" 5 times.) But it doesn't work? Help please!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char s[80];
int len;
int counter = 0;
char* repeat(char* s, int n) {
if (n > 0) {
if (s[len] == n) {
counter++;
}
len--;
repeat(s, (n++));
}
return s;
}
int main(void) {
printf("%s", repeat("vb", 5));
fflush(stdout);
return EXIT_SUCCESS;
}
You're trying to write into the end of "vb" which is a string in the constant pool. Don't do that. Allocate a string that is strlen(s) * n + 1 long and write into that.
Your base case is probably wrong. The base case should probably be when n == 0 which is when the empty string (nothing appended except terminating NUL as below) is appropriate.
Your recursive step (n++) should probably be (n - 1) to count down to that base case. As written, the post-increment does a useless assign and recurses with the same value of n.
I don't know what counter and len are supposed to do, but they looks redundant to me. len is uninitialized, so s[len] has undefined behavior.
After writing the n copies, you need to add a terminating NUL ('\0') at the end so that printf and similar functions can identify the end.
You are using s both as a global and a local variable, the function is working on the local.
Try not to use global variables where not necessary. Also, recursion is not necessary for this.
#include <stdio.h>
void concatenate_string(char *dest, const char *src, int n) {
char *s;
while(n--) {
s = (char*)src;
while(*(s))
*(dest++)=*(s++);
}
*(dest++) = 0;
}
int main(void) {
char out[80];
concatenate_string(out, "ab", 5);
printf("%s", out);
return 0;
}
Related
Hy I have a sample code bleow, which should write the "MSG" in a way an LCD display would (running text) and when it reached the end it strarts again, but when I allocate memory for the "LCD" (which schould be 10 character+terminating 0) fills it with bunch of random characters.
Sample picture
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
void delay(unsigned int mseconds)
{
clock_t goal = mseconds + clock();
while (goal > clock());
}
int main()
{
int LCDSize = 10;
int MSGSize;
char* LCD = (char *)malloc(LCDSize+1);
char* MSG = (char *)malloc(80);
MSG = "This is a long message, probabli will move.";
MSGSize = strlen(MSG);
if (MSGSize <= LCDSize)
{
printf(MSG);
}
else
{
char* tmpMSG;
int j = 0;
while (j < 2)
{
for (int i = 0; i < MSGSize - LCDSize + 1; i++)
{
tmpMSG = MSG+i;
strncpy(LCD, tmpMSG, LCDSize);
strcat(LCD,"\0");
printf(LCD);
delay(200);
system("cls");
}
printf("----------");
j++;
}
}
getchar();
return 0;
}
What could be the problem?
strncpy(LCD, tmpMSG, LCDSize);
strcat(LCD,"\0");
The strncpy function will not terminate if it doesn't fit. In this case, it doesn't fit. So there is no termination. Something that is not terminated with a zero byte is not a legal string, so you cannot pass a pointer to it as the first parameter to strcat, but you do.
The strcat function appends one string onto another. Both strings must be legal, well-formed strings or you must not call strcat.
This is one of the reasons it is generally suggested that you not use strncpy -- there is no guarantee the result is a valid string and it's easy to make the kind of mistake you made. Yes, you made sure you didn't overflow the buffer when you called strncpy by limiting the size, but you didn't ensure the buffer contained a valid string.
What you probably wanted was LCD[LCDSize]='\0'; instead of the call to strcat. This ensures the buffer is terminated.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
My program need to print all the ABC but I see I have problems with the code. How I can fix it? (no pointer for this time).
What is the runtime error in the code and how to fix it?
Here is the code:
// Elvis’s hip and happening ABC-printing code
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET 26
void makeABC(char abc[NUM_ABC_LET]);
int main() {
char abcString[NUM_ABC_LET] = "";
makeABC(abcString);
puts(abcString);
return (0);
}
void makeABC(char abc[NUM_ABC_LET]) {
char letter;
for (letter = 'a'; letter <= 'z'; letter++) {
strcat(abc, letter);
}
}
The problem is that the strcat function expects both arguments to be (zero-terminated) strings. You only pass one string, and then one single character as arguments (which should give you compiler warnings).
You need to convert this single characters into a string (or an array) of a single character.
And don't forget that strings in C are zero-terminated.
What happens you use the single character as argument to the strcat function is that the compiler converts it to an int which is then in turn converted to a pointer. The problem with this is that the address 'a' (for example) is not a valid address to a string. That will lead to undefined behavior and a crash.
Your program logic is correct, the problem is the calling of the strcat() function. The strcat() function is implemented as:
char *strcat(char *dest, const char *src)
{
char *ret = dest;
while (*dest)
dest++;
while (*dest++ = *src++);
return ret;
}
The second argument must be a string instead which you pass a character.
This is the reason for your run time error.
Can you try something like following? I haven't tested the following but it should work on most part.
// Elvis’s hip and happening ABC-printing code
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET 26
void makeABC(char abc[NUM_ABC_LET]);
int main()
{
char abcString[NUM_ABC_LET + 1];
makeABC(abcString);
puts(abcString);
return 0;
}
void makeABC(char abc[NUM_ABC_LET + 1])
{
char letter;
int i=0;
for(letter = 'a'; letter <= 'z'; letter++)
{
abc[i] = letter;
i++;
}
abc[i]='\0';
}
Your program has several issues:
You cannot call strcat with a char, you must pass char * arguments, pointing to null terminated C strings.
The array into which you compose the alphabet is too short: you need to define it with a size one larger than the number of characters for the final '\0' terminator.
Here is a corrected version:
#include <stdio.h>
#include <string.h>
#define NUM_ABC_LET ('z' - 'a' + 1) // 26 ASCII letters
void makeABC(char *abc); // makeABC receives a pointer to an array of char
// this declaration is equivalent to
// void makeABC(char abc[NUM_ABC_LET+1]);
// but less error prone
int main(void) {
char abcString[NUM_ABC_LET + 1] = "";
makeABC(abcString);
puts(abcString);
return 0;
}
void makeABC(char *abc) {
char letter;
char buf[2]; // a buffer for a 1 letter C string
for (letter = 'a'; letter <= 'z'; letter++) {
buf[0] = letter; // make a 1 letter string
buf[1] = '\0'; // set the null terminator
strcat(abc, buf);
}
}
Prototype of strcat is
char *strcat(char *destination, const char *source);
means our source as well as destinations should and must be string so this is the issue that why if you compile in turbo c it will through error of
"type mismatch".
and if you wanna write program for printing ABC up to Z than simply write
void main()
{
int i;
for(i = 65; i<=90; i++)
{
printf("%c", i);
}
}
I hope you will like it......
As a slight variation, I would suggest passing the length of the character array to the function, so that the function does not overflow the array.
As the character array is passed to the function as a pointer, the function does not know it's size.
In your case you know the size, but for the future it might be better to explicitly pass the size.
Also I just copied the characters rather than use strcat, and added the null termination at the end.
#include <stdio.h>
#define NUM_ABC_LET 26
/* function takes pointer to array and size of array */
void makeABC(char *abc, int len);
int main()
{
/* array needs to include space for null termination */
char abcString[NUM_ABC_LET + 1];
/* call function with pointer + size */
makeABC(abcString, NUM_ABC_LET);
printf("%s\n", abcString);
return (0);
}
void makeABC(char *abc, int len)
{
int n;
for(n = 0; n < len; n++ ) {
/* add letters to the array */
abc[n] = n + 'a';
}
/* put a null termination on the end */
abc[n] = '\0';
}
I have created a function for strend, which basically returns 1 if string t is present at the end of string s, however it never returns 1:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int strend(char *s, char *t) {
int p;
for (p = 0; p < strlen(s) - strlen(t); p++) {
*s++;
}
printf("%s\n%s\n", s, t);
if (s == t)
return 1;
return 0;
}
int main(void) {
int bool = strend("Hello", "ello");
printf("%i\n", bool);
return 0;
}
This gives me an output of:
ello
ello
0
So technically I should get 1. I assume the comparison using pointers is not used in this way?
You need to review your basic knowledge of C strings. There are lots of standard string functions in string.h that can help you with this test.
The basic problem is that the test s == t is valid, but you are comparing memory addresses here. You can see that is valid if you change the strings to test to
char test[] = "Hello";
int bool = strend_(test, test+1);
where test obviously is the same as your "Hello", and similarly, test+1 is the same as "ello" (try it by printing them). This correctly returns 1 with your routine.
In addition, I get two warnings:
on *s++; "warning: expression result unused [-Wunused-value]": you increment s but also ask what character is at that position through *s; and you don't use that information.
Fix by removing the * there.
on p < strlen(s) ..; "warning: comparison of integers of different signs: 'int' and 'unsigned long'", because strlen does not return a signed integer but an unsigned one (apparently, my header uses unsigned long).
Fix by declaring p as unsigned long, or even better, size_t.
Your entire routine can be condensed to a simple
int strend (char *s, char *t)
{
if (strlen(s) >= strlen(t) && !strcmp (s+strlen(s)-strlen(t),t))
return 1;
return 0;
}
It's not worth the trouble to cache the result of those four strlen calls into 2 temporary variables; a good compiler will work it out and do that for you. (A quick glance to the assembly output of the compiler I'm using – clang – shows it does, even with the default optimization settings.)
A slightly modified test, based on #M.M.'s comment:
int strend (char *s, char *t)
{
if (strlen(s) < strlen(t)) return 0;
return !strcmp (s+strlen(s)-strlen(t),t);
}
but attempting to optimize it this way is not as easy parsed as the routine above, and its assembly is ever so slightly "wordy" as well. Personally, I'd go for the more humanly readable version.
Use strcmp(3)
if (strcmp(s, t) == 0) return 1;
This actually compares the contents of the memory pointed to by s and t rather than their addresses.
Your code is broken in multiple ways:
The initial loop is a very cumbersome way to advance p by the difference of lengths if positive.
Once you have pointers at the same distance from the end of both strings, You should compare the characters with strcmp() (or memcmp() if you can first exclude the case of strlen(s) < strlen(t).
Comparing the pointers obtained after the loop will only work if t points inside the string pointed to by s, a special case that may or may not be produced by the compiler for the specific call in main: strend("Hello", "ello");.
Here is a modified version:
#include <string.h>
int strend(const char *str1, const char *str2) {
size_t len1 = strlen(str1);
size_t len2 = strlen(str2);
return len1 >= len2 && !memcmp(str1 + len1 - len2, str2, len2);
}
I corrected/modified your code, here is the code,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#pragma warning(disable:4996)
int strend(char *s, char *t)
{
int p,flag=0,count=0;//count will be the starting index for *t
p = strlen(s) - strlen(t);//this will be the starting index for *s
while(count<strlen(t))
{
if (*(s+p) == *(t+count))
{
flag = 1;
count++;
p++;
continue;
}
else
{
flag = 0;
break;
}
}
return flag;
}
int main(void)
{
int flag = strend("Hello", "ello");
printf("%i\n", flag);
return 0;
}
This code works too.
#include <stdio.h>
#include <string.h>
int strend (char *s1, char *s2);
void main ()
{
char str1[20] = "somethings";
char str2[20] = "things";
int f;
f = strend (str1,str2);
if (f==1)
printf ("1");
else
printf ("0");
}
int strend (char *str1, char *str2)
{
int l = strlen(str1) - strlen(str2);
str1 = str1 + l;
int d = strcmp(str1,str2);
if (d == 0)
return 1;
else
return 0;
}
this code works well.
int strend(char *s, char *t){
while(*t & *s){
if(*t == *s){
t++;
}
s++;
}
return *t==*s;
}
I have the following code:
#include <stdio.h>
void insertion_sort(char[], int);
void swap(char*, char*);
int main() {
char s[] = "hello world";
puts(s);
insertion_sort(s, sizeof(s)/sizeof(char));
puts("done\n");
puts(s);
return 0;
}
void swap(char* a, char* b) {
char tmp = *a;
*a = *b;
*b = tmp;
}
void insertion_sort(char s[], int n)
{
int i,j;
/* counters */
for (i=1; i<n; i++) {
j=i;
while ((j>0) && (s[j] < s[j-1])) {
swap(&s[j],&s[j-1]);
j = j-1;
}
printf("%s\n", s);
}
}
The problem is, after the insertion_sort() function call, s becomes empty - puts(s) prints nothing.
Please advise.
Change:
insertion_sort(s, sizeof(s)/sizeof(char));
to:
insertion_sort(s, strlen(s));
otherwise you will be including the '\0' terminator of s[] in your sort.
Note that you will need an additional header for strlen so change:
#include <stdio.h>
to:
#include <stdio.h> // printf etc
#include <string.h> // strlen etc
The problem is that the length that you pass to insertion_sort includes terminating \0 character, which happens to have value 0, so in sort it is placed as the first element of your array. This is why your last puts() prints nothing - because the first character is now "the end of a string".
I suggest you to calculate the size of a string using strlen() which will return the length of a string excluding terminating character. Or if you want to do it your way, take terminating character into consideration and substract it from the total length.
So I'm working on a program where the function reads in from stdio, and keeps reading in characters in chunks of n characters.
So far I've gotten it so that everything is stored in a character array called buffer. For the next step, I need to sort each chunk of n characters. For example the string cats/ndogs/n should be split as cats/n dogs/n if n =5, and then qsort() needs to alphabetize it. This is how I'm calling qsort():
qsort (buffer, (line-2)*n*(sizeof(char)),n,compare);
Where (line-2)*n*sizeof(char) gives the total number of items in the array buffer; 10 in this case.
This is my compare function:
int compare (const void * a, const void * b)
{
return (strcmp(*(char **)a, *(char **)b));
}
When I run this, however, I always get a seg fault in strcmp(). Any ideas why?
This is the loading code:
while (!feof(stdin))
{
for (i = 0; i < n; i++)
{
char l = getchar();
if (l != EOF)
{
if ((i == 0) && (line != 1))
{
success = (int *)realloc(buffer, line*n*(sizeof(char)));
}
buffer[(n*(line-1))+i] = l;
}
}
line = line + 1;
}
Silly question, but are your strings null terminated? You seem to only have a newline on the end.
Also, you probably only need "strcmp((char *)a, (char *)b)" as the extra *s look to be redundant to me.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buffer[] ="333000222555111777888666999444";
int mycmp(void *l, void*r);
int main(void)
{
/* note: sizeof buffer is 31,
** but the integer division will round down
** , ignoring the extra nul-byte */
qsort(buffer, (sizeof buffer/3), 3, mycmp);
printf ("[%s]\n", buffer);
return 0;
}
int mycmp(void *l, void *r)
{
return memcmp(l,r,3);
}