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.
Related
So I have used malloc() to create an array of pointers. I ultimately want to have an array of strings. How would I come about assigning a string value to one of these malloced pointers?
For example if I have done the following:
char ** elements= malloc(N* sizeof(char*));
and looped the previous array to malloc the individual pointers like this:
elements[i] = malloc((50) * sizeof(char));
We can copy something into the string using strncpy() and similair functions, for example memcpy() or using our own function.
I recommend using strncpy() since it protects against overflows because it copies a till a length specified.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char BYTE;
enum {
NumStrings = 50,
MaxStrLen = 50
};
int main(void) {
char **StrList = malloc(NumStrings * sizeof(char *));
if (StrList == NULL) {
perror("malloc");
exit(1);
}
for (BYTE i = 0; i < NumStrings; i++) {
StrList[i] = malloc(MaxStrLen);
if (StrList[i] == NULL) {
perror("malloc");
exit(1);
}
// Here we copy something into the string for example
strncpy(StrList[i], "test", 50);
StrList[i][49] = '\0';
// Print string here to show it's copied
printf("%s ", StrList[i]);
}
putchar('\n');
for (BYTE i = 0; i < NumStrings; i++)
free(StrList[i]);
free(StrList);
exit(0);
}
With current standard C, you would do:
#include <stdlib.h>
#include <string.h>
size_t size = strlen(some_string) + 1; // +1 for null term
elements[i] = malloc(size);
memcpy(elements[i], some_string, size);
...
free(elements[i]);
With the upcoming "C2x" standard (still in draft stages), strdup will likely get added to the language. Though it's already widely available as a non-standard extension supported by POSIX. Example:
#include <string.h>
elements[i] = strdup(some_strings[i]);
...
free(elements[i]);
Use #include <string.h> to include string functions.
Than use strncpy function to assign a value to char array. To copy a string to elements[i], use this:
strncpy(elements[i], "Hello, world!", 49)
You can put another char array pointer as second argument. Please note, that to avoid erasing null-byte at the end of string, substract 1 from actual string array length to keep last byte for '\0'. Also, it's better to use calloc(50, sizeof(char)) to allocate strings, because calloc additionally fills them with null bytes. Or, at least, add this line while iterating (set last byte to zero to make string null-terminated):
elements[i][49] = '\0';
I've been trying to code a really simple string to morse code converter in C for a few hours now and I finally got it to compile without any warnings. I'm a beginner in C so I really cannot understand how to fix my code. I believe the problem should be in how I pass strings around with pointers and etc, since this is the part I do not understand the most. I found an example on how to do it, but I still couldn't understand it, and there wasn't any specific case that would be similar to mine, since I want it to read strings from the arguments (all arguments are strings/words).
And now I'm getting a segmentation fault when trying to run it:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int to_morse(char *);
int main(int argc, char **argv)
{
char morse[80];
char *temp;
for (int counter = 1; counter < argc; counter++)
{
*temp = to_morse(argv[counter]);
strcat(temp, morse);
printf("%s", morse);
}
return 0;
}
int to_morse(char *str)
{
char *morse[27] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
char *output;
char character;
for (int counter = 0; str[counter] != '\0'; counter++)
{
character = toupper(str[counter]);
strcat(morse[character-'A'], output);
}
return *output;
}
I believe this is not a correct way to pass around strings using pointers, but I cannot figure out the right way. How would I be able to make my code work?
Note: I'm aware this might have a duplicate somewhere.. however, there are tons of segmentation fault questions and all of them are really specific and do not cover my scenario, so I couldn't find one.
There is so much going wrong with your code.
Firstly, strcat takes 2 parameters - a destination and then a source. In all cases that you're using it, you've got them the wrong way around.
Secondly, your function to_morse returns an int when you want it to return a char *. That would be how you pass around pointers.
Thirdly, you don't allocate any memory for output in that function, so even if you had the strcat the right way around, you've not got anywhere to store the morse code. That'll also be where the code is crashing as you're passing in an uninitialised pointer to strcat.
Finally, you should probably check that the character you're trying to convert to morse is a letter, otherwise you'll go out of bounds on your array.
Here is how your code should look. I've also tweaked it so that you put a space between each morse "letter" as otherwise you'd not be able to tell where one begins and another ends.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
char *to_morse(char *);
int main(int argc, char **argv)
{
char *temp;
for (int counter = 1; counter < argc; counter++)
{
temp = to_morse(argv[counter]);
printf("%s", temp);
free(temp); // Always remember to free memory you allocate
}
return 0;
}
char *to_morse(char *str)
{
char *morse[27] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
char *output=malloc((strlen(str)*5)+1); // Always remember to allocate 1 more char than you need to store the NUL terminate when allocating memory for strings.
output[0] = '\0'; // strcat need a null terminator in the string.
char character;
for (int counter = 0; str[counter] != '\0'; counter++)
{
if(isalpha(str[counter]))
{
character = toupper(str[counter]);
strcat(output,morse[character-'A']);
strcat(output," ");
}
}
return output;
}
I'm trying to take an input string like 12340 and output 4321. The weird thing is, if I put a sequence that is smaller than 4 (ex : 1230), the output is correct (321). But if I input 12340, I end up having 4321(↨#. What causes this behavior?
(This is no homework, I'm following exercice 6.8 of http://www.ltam.lu/cours-c/prg-c58.htm to learn C)
Here is my whole code (I would post a small/concise code example but I can't seem to put the finger on the problem)
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
char array[100];
printf("Shoot me consecutive numbers, end with 0\n");
scanf("%s",&array);
int count = strlen(array);
char countdown[count];
int reverseIndex;
int index = 0;
for(reverseIndex = count-1;reverseIndex >= 0;reverseIndex--)
{
char possibleNumber = array[reverseIndex];
if(isdigit(possibleNumber) && possibleNumber != '0')
{
countdown[index] = possibleNumber;
index++;
}
}
printf("countdown : %s\n",countdown);
return 0;
}
One immediate error is this line:
you need to provide enough room for the NULL terminator in this line:
char countdown[count + 1];//added +1
Another is:
scanf("%s",&array);
Change it to:
scanf("%s",array); //%s expects char *, &array is of type char (*)[100], parameter type mismatch
I made these edits to the original code (see in-line comments), also used call to memset() to initialize countdown, and it runs: (results shown below)
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
char array[100];
printf("Shoot me consecutive numbers, end with 0\n");
scanf("%s",array);//removed &
int count = strlen(array);
char countdown[count+1];//add room for NULL terminator
int reverseIndex;
int index = 0;
memset(countdown, 0, count+1);//added to initialize all elements of char array to NULL
for(reverseIndex = count-1;reverseIndex >= 0;reverseIndex--)
{
char possibleNumber = array[reverseIndex];
if(isdigit(possibleNumber) && possibleNumber != '0')
{
countdown[index] = possibleNumber;
index++;
}
}
printf("countdown : %s\n",countdown);
getchar();
getchar();
return 0;
}
Input and output:
EDIT to answer comment question about undesired characters in result
(and original question: ...But if I input 12340, I end up having 4321(↨#... )
When char countdown[count+1]; is created, there is no guarantee of the contents.
That is, each position can be filled with any random set of bits.
Say array is defined as char array[5]; If not initialized, it may look like this in memory:
|€|Œ|™|¢|§|
Later in your code, you loop through to make assignments to each position to
populate with characters obtained using `scanf() from stdin, which is fine,
Now, it looks like this after looping 4 times:
|1|2|3|4|§|
Note, there is not a terminating NULL (0) in the last position.
By using memset(array, 0, 5); the created buffer would look like this:
|0|0|0|0|0|
And the resulting populated buffer like this:
|1|2|3|4|0| //properly terminated char buf is required for a C string
The countdown array isn't NULL terminated so printf doesn't know where to stop.
You'll want to allocate count + 1 characters and then set the last character to NULL.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main()
{
char array[100];
printf("Shoot me consecutive numbers, end with 0\n");
scanf("%s",&array);
int count = strlen(array);
char countdown[count + 1];
int reverseIndex;
int index = 0;
for(reverseIndex = count-1;reverseIndex >= 0;reverseIndex--)
{
char possibleNumber = array[reverseIndex];
if(isdigit(possibleNumber) && possibleNumber != '0')
{
countdown[index] = possibleNumber;
index++;
}
}
countdown[index] = 0;
printf("countdown : %s\n",countdown);
return 0;
}
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;
}
I am tring to create a sub-routine that inserts a string into another string. I want to check that the host string is going to have enough capacity to hold all the characters and if not return an error integer. This requires using something like sizeof but that can be called using a pointer. My code is below and I would be very gateful for any help.
#include<stdio.h>
#include<conio.h>
//#include "string.h"
int string_into_string(char* host_string, char* guest_string, int insertion_point);
int main(void) {
char string_one[21] = "Hello mother"; //12 characters
char string_two[21] = "dearest "; //8 characters
int c;
c = string_into_string(string_one, string_two, 6);
printf("Sub-routine string_into_string returned %d and creates the string: %s\n", c, string_one);
getch();
return 0;
}
int string_into_string(char* host_string, char* guest_string, int insertion_point) {
int i, starting_length_of_host_string;
//check host_string is long enough
if(strlen(host_string) + strlen(guest_string) >= sizeof(host_string) + 1) {
//host_string is too short
sprintf(host_string, "String too short(%d)!", sizeof(host_string));
return -1;
}
starting_length_of_host_string = strlen(host_string);
for(i = starting_length_of_host_string; i >= insertion_point; i--) { //make room
host_string[i + strlen(guest_string)] = host_string[i];
}
//i++;
//host_string[i] = '\0';
for(i = 1; i <= strlen(guest_string); i++) { //insert
host_string[i + insertion_point - 1] = guest_string[i - 1];
}
i = strlen(guest_string) + starting_length_of_host_string;
host_string[i] = '\0';
return strlen(host_string);
}
C does not allow you to pass arrays as function arguments, so all arrays of type T[N] decay to pointers of type T*. You must pass the size information manually. However, you can use sizeof at the call site to determine the size of an array:
int string_into_string(char * dst, size_t dstlen, char const * src, size_t srclen, size_t offset, size_t len);
char string_one[21] = "Hello mother";
char string_two[21] = "dearest ";
string_into_string(string_one, sizeof string_one, // gives 21
string_two, strlen(string_two), // gives 8
6, strlen(string_two));
If you are creating dynamic arrays with malloc, you have to store the size information somewhere separately anyway, so this idiom will still fit.
(Beware that sizeof(T[N]) == N * sizeof(T), and I've used the fact that sizeof(char) == 1 to simplify the code.)
This code needs a whole lot more error handling but should do what you need without needing any obscure loops. To speed it up, you could also pass the size of the source string as parameter, so the function does not need to calculate it in runtime.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
signed int string_into_string (char* dest_buf,
int dest_size,
const char* source_str,
int insert_index)
{
int source_str_size;
char* dest_buf_backup;
if (insert_index >= dest_size) // sanity check of parameters
{
return -1;
}
// save data from the original buffer into temporary backup buffer
dest_buf_backup = malloc (dest_size - insert_index);
memcpy (dest_buf_backup,
&dest_buf[insert_index],
dest_size - insert_index);
source_str_size = strlen(source_str);
// copy new data into the destination buffer
strncpy (&dest_buf[insert_index],
source_str,
source_str_size);
// restore old data at the end
strcpy(&dest_buf[insert_index + source_str_size],
dest_buf_backup);
// delete temporary buffer
free(dest_buf_backup);
}
int main()
{
char string_one[21] = "Hello mother"; //12 characters
char string_two[21] = "dearest "; //8 characters
(void) string_into_string (string_one,
sizeof(string_one),
string_two,
6);
puts(string_one);
return 0;
}
I tried using a macro and changing string_into_string to include the requirement for a size argument, but I still strike out when I call the function from within another function. I tried using the following Macro:
#define STRING_INTO_STRING( a, b, c) (string_into_string2(a, sizeof(a), b, c))
The other function which causes failure is below. This fails because string has already become the pointer and therefore has size 4:
int string_replace(char* string, char* string_remove, char* string_add) {
int start_point;
int c;
start_point = string_find_and_remove(string, string_remove);
if(start_point < 0) {
printf("string not found: %s\n ABORTING!\n", string_remove);
while(1);
}
c = STRING_INTO_STRING(string, string_add, start_point);
return c;
}
Looks like this function will have to proceed at risk. looking at strcat it also proceeds at risk, in that it doesn't check that the string you are appending to is large enough to hold its intended contents (perhaps for the very same reason).
Thanks for everyone's help.