I am trying to add integers to a string. When I debug my code everything works perfectly fine, but when i run it normally two unwanted characters are being printed at the beginning of the string. How do I avoid this?
int number_of_ints = 5;
char s[number_of_ints*2];
char suffix[4];
for(int i = 1; i <= number_of_ints; i++){
snprintf(suffix, number_of_ints, "%d*", i);
strncat(s, suffix, 2);
printf("%s\n", s);
}
This is the output when building and running the code normally.
`û1*
`û1*2*
`û1*2*3*
`û1*2*3*4*
`û1*2*3*4*5*
Strings in C are a sequence of nonzero bytes followed by a terminating byte with a value of zero (the null-terminating byte, '\0').
You must size your buffer to have an additional space, to guarantee room for this null-terminating byte.
You must additionally make sure the contents of the buffer contain a valid string. You can do this by setting the first element of the buffer to the null-terminating byte, creating a zero-length string.
Failing to initialize the contents of your buffer means it will contain indeterminate values, and passing such a buffer to a function expecting a valid string will invoke Undefined Behavior.
The second argument to snprintf should be, at most, the size of the destination buffer.
Finally, consider using size_t when applicable, as it is the appropriate type for dealing with memory sizes (e.g., sizing variable-length arrays; the sizeof operator resolves to this type; snprintf expects this type as its second argument).
#include <stdio.h>
#include <string.h>
int main(void) {
size_t number_of_ints = 5;
char s[number_of_ints * 2 + 1];
char suffix[4];
s[0] = '\0';
for (size_t i = 1; i <= number_of_ints; i++) {
snprintf(suffix, sizeof suffix, "%zu*", i);
strncat(s, suffix, 2);
printf("%s\n", s);
}
}
You have a few issues with initialization and size of your buffers.
The size of your buffer is too short by 1 byte that is needed for 0-termination. Adding the last number causes buffer overrun and undefined behaviour.
In addition the calculated size is only sufficient as long as number_of_ints<10 because it only allows for single digit numbers.
That buffer is not initialized and us very likely not holding an empty string. Accessing it (via strcat etc.) invokes undefined behaviour.
The size you provide to snprintf is not related to the size of the buffer.
You should apply these changes:
#include <stdio.h>
#include <string.h>
int main(void)
{
int number_of_ints = 5;
char s[number_of_ints*2+1];
char suffix[4];
s[0] = 0;
for (int i = 1; i <= number_of_ints; i++)
{
snprintf(suffix, sizeof(suffix), "%d*", i);
strncat(s, suffix, 2);
printf("%s\n", s);
}
}
Related
Hello I am working on a Caesar encryption program. Right now it takes as an input the file with the message to encrypt, the key
The input is currently in this format:
"text.txt", "ccc"
I need to convert this into taking a number so that it fits my requirements, so something like this:
"text.txt", "3"
Then i need to convert this "3" back into "ccc" so that the program still works. The logic being that 3 translates to the third letter of the alphabet "c", and is repeated 3 times. Another example would be if the key entered is "2", it should return "bb".
This is what i have so far but its giving me a lot of warnings and the function does not work correctly.
#include <stdio.h>
void number_to_alphabet_string(int n) {
char buffer[n];
char *str;
str = malloc(256);
char arr[8];
for(int i = 0; i < n; i++) {
buffer[i] = n + 64;
//check ASCII table the difference is fixed to 64
arr[i] = buffer[i];
strcat(str, arr);
}
printf(str);
}
int main(int argc, char *argv[]) {
const char *pt_path = argv[1]; //text.txt
char *key = argv[2]; //3
number_to_alphabet_string((int)key); //should change '3' to 'CCC'
}
Your problem is that you have a function
void number_to_alphabet_string(int n)
that takes an int but you call it with a char*
char* key = argv[2]; //3
number_to_alphabet_string(key);
My compiler says
1>C:\work\ConsoleApplication3\ConsoleApplication3.cpp(47,34): warning C4047: 'function': 'int' differs in levels of indirection from 'char *'
You need
char* key = argv[2]; //3
number_to_alphabet_string(atoi(key));
to convert that string to a number
With char *key = argv[2];, the cast (int) key does not reinterpret the contents of that string as a valid integer. What that cast does is take the pointer value of key, and interprets that as an integer. The result of this is implementation-defined, or undefined if the result cannot be represented in the integer type (a likely outcome if sizeof (int) < sizeof (char *)).
The C standard does not define any meaning for these values.
Here is a test program that, depending on your platform, should give you an idea of what is happening (or failing to happen)
#include <stdio.h>
int main(int argc, char **argv) {
if (sizeof (long long) >= sizeof (char *))
printf("Address %p as an integer: %lld (%llx)\n",
(void *) argv[0],
(long long) argv[0],
(long long) argv[0]);
}
As an example of implementation-defined behaviour, on my system this prints something like
Address 0x7ffee6ffdb70 as an integer: 140732773948272 (7ffee6ffdb70)
On my system, casting that same pointer value to (int) results in undefined behaviour.
Note that intptr_t and uintptr_t are the proper types for treating a pointer value as an integer, but these types are optional.
To actually convert a string to an integer, you can use functions such as atoi, strtol, or sscanf. Each of these have their pros and cons, and different ways of handling / reporting bad input.
Examples without error handling:
int three = atoi("3");
long four = strtol("4", NULL, 10);
long long five;
sscanf("5", "%lld", &five);
number_to_alphabet_string has a few problems.
malloc can fail, returning NULL. You should be prepared to handle this event.
In the event malloc succeeds, the contents of its memory are indeterminate. This means that you need to initialize (at least partially) the memory before passing it to a function like strcat, which expects a proper null terminated string. As is, strcat(str, arr); will result in undefined behaviour.
Additionally, memory allocated by malloc should be deallocated with free when you are done using it, otherwise you will create memory leaks.
char *foo = malloc(32);
if (foo) {
foo[0] = '\0';
strcat(foo, "bar");
puts(foo);
free(foo);
}
In general, strcat and the additional buffers are unnecessary. The use of char arr[8]; in particular is unsafe, as arr[i] = buffer[i]; can easily access the array out-of-bounds if n is large enough.
Additionally, in strcat(str, arr);, arr is also never null terminated (more UB).
Note also that printf(str); is generally unsafe. If str contains format specifiers, you will again invoke undefined behaviour when the matching arguments are not provided. Use printf("%s", str), or perhaps puts(str).
As far as I can tell, you simply want to translate your integer value n into the uppercase character it would be associated with if A=1, B=2, ... and repeat it n times.
To start, there is no need for buffers of any kind.
void number_to_alphabet_string(int n) {
if (1 > n || n > 26)
return;
for (int i = 0; i < n; i++)
putchar('A' + n - 1);
putchar('\n');
}
When passed 5, this will print EEEEE.
If you want to create a string, ensure there is an additional byte for the terminating character, and that it is set. calloc can be used to zero out the buffer during allocation, effectively null terminating it.
void number_to_alphabet_string(int n) {
if (1 > n || n > 26)
return;
char *str = calloc(n + 1, 1);
if (str) {
for (int i = 0; i < n; i++)
str[i] = 'A' + n - 1;
puts(str);
free(str);
}
}
Note that dynamic memory is not actually needed. char str[27] = { 0 }; would suffice as a buffer for the duration of the function.
A cursory main for either of these:
#include <stdio.h>
#include <stdlib.h>
void number_to_alphabet_string(int n);
int main(int argc, char *argv[]) {
if (argc > 1)
number_to_alphabet_string(atoi(argv[1]));
}
Note that with an invalid string, atoi simply returns 0, which is indistinguishable from a valid "0" - a sometimes unfavourable behaviour.
You can't use a cast to cast from a char array to an int, you have to use functions, such as atoi().
You never free your str after you allocate it. You should use free(str) when you no longer need it. Otherwise, it will cause a memory leak, which means the memory that you malloc() will always be occupied until your process dies. C doesn't have garbage collection, so you have to do it yourself.
Don't write things such as char buffer[n];, it can pass the compile of GCC, but it can't in MSVC.
And that isn't the stander way of declaring an array with variable length. use
char* buffer = malloc(n);
//don't forget to free() in order to avoid a memory leak
free(buffer);
I need help with char array. I want to create a n-lenght array and initialize its values, but after malloc() function the array is longer then n*sizeof(char), and the content of array isnt only chars which I assign... In array is few random chars and I dont know how to solve that... I need that part of code for one project for exam in school, and I have to finish by Sunday... Please help :P
#include<stdlib.h>
#include<stdio.h>
int main(){
char *text;
int n = 10;
int i;
if((text = (char*) malloc((n)*sizeof(char))) == NULL){
fprintf(stderr, "allocation error");
}
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
int test = strlen(text);
printf("\n%d\n", test);
puts(text);
free(text);
return 0;
}
Well before using strcat make
text[0]=0;
strcat expects null terminated char array for the first argument also.
From standard 7.24.3.1
#include <string.h>
char *strcat(char * restrict s1,
const char * restrict s2);
The strcat function appends a copy of the string pointed to by s2
(including the terminating null character) to the end of the string
pointed to by s1. The initial character of s2 overwrites the null
character at the end of s1.
How do you think strcat will know where the first string ends if you don't
put a \0 in s1.
Also don't forget to allocate an extra byte for the \0 character. Otherwise you are writing past what you have allocated for. This is again undefined behavior.
And earlier you had undefined behavior.
Note:
You should check the return value of malloc to know whether the malloc invocation was successful or not.
Casting the return value of malloc is not needed. Conversion from void* to relevant pointer is done implicitly in this case.
strlen returns size_t not int. printf("%zu",strlen(text))
To start with, you're way of using malloc in
text = (char*) malloc((n)*sizeof(char)
is not ideal. You can change that to
text = malloc(n * sizeof *text); // Don't cast and using *text is straighforward and easy.
So the statement could be
if(NULL == (text = (char*) malloc((n)*sizeof(char))){
fprintf(stderr, "allocation error");
}
But the actual problem lies in
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
The strcat documentation says
dest − This is pointer to the destination array, which should contain
a C string, and should be large enough to contain the concatenated
resulting string.
Just to point out that the above method is flawed, you just need to consider that the C string "A" actually contains two characters in it, A and the terminating \0(the null character). In this case, when i is n-2, you have out of bounds access or buffer overrun1. If you wanted to fill the entire text array with A, you could have done
for(i = 0; i < n; i++){
// Note for n length, you can store n-1 chars plus terminating null
text[i]=(n-2)==i?'A':'\0'; // n-2 because, the count starts from zero
}
//Then print the null terminated string
printf("Filled string : %s\n",text); // You're all good :-)
Note: Use a tool like valgrind to find memory leaks & out of bound memory accesses.
I am trying to get just the phone number out of the string passed into getPhoneNumber(char[] str), but for some reason, i get some random character appended to it each time i run the code, please i need help.
source code
#include <stdio.h>
#include <string.h>
char* getPhoneNumber(char str[]);
int main(){
getPhoneNumber("AT+CMGR=5 \n+CMGR: \"REC READ\",\"+9349036332058\",\"samuel\",\"17/03/31,20:44:52+04\"\nHOW THINS fa OK");
return 0;
}
char* getPhoneNumber(char str[]){
char *temp = strchr(str, ',')+2;
const unsigned short len1 = strlen(temp);
printf("value in temp : %s\n\n",temp);
char *strPtr = strchr(temp, '\"');
const unsigned short len2 = strlen(strPtr);
printf("value in strPtr : %s\n\n",strPtr);
int phone_num_len = len1-len2;
char phone_num[phone_num_len];
strncpy(phone_num, temp,phone_num_len);
printf("Phone number : %s",phone_num);
}
I also printed out individual values of temp and strPtr for debugging purposes, but the returned values seems ok.
The output of the program is shown in the image below.
You're not setting aside enough space for phone_num. As a result, printf is reading past the end of the array. This invokes undefined behavior. That is why you see extra characters when running locally but it appears to work fine on ideone (it also appears to run fine for me).
You need one more byte for the null terminating character for the string. Also, you need to manually add that null terminator since the strncpy function won't do it for you since there's no null terminator within phone_num_len bytes of temp.
char phone_num[phone_num_len+1];
strncpy(phone_num, temp,phone_num_len);
phone_num[phone_num_len] = '\0';
From the man page for strncpy(char * dst, const char * src, size_t len):
If src is less than len characters long, the remainder of dst is filled with `\0' characters. Otherwise, dst is not terminated.
So it is not, as you seem to expect, terminating the "string" you are copying.
I am rather new to the C language right now and I am trying some practice on my own to help me understand how C works. The only other language I know proficiently is Java. Here is my code below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char * reverse(char word[]);
const char * reverse(char word[]) {
char reverse[sizeof(word)];
int i, j;
for (i = sizeof(word - 1); i <= 0; i--) {
for (j = 0; j > sizeof(word - 1); j++) {
reverse[i] = word[j];
}
}
return reverse;
}
int main() {
char word[100];
printf("Enter a word: ");
scanf("%s", word);
printf("%s backwards is %s\n", word, reverse(word));
return 0;
}
When the user enters a word, the program successfully prints it out when i store it but when i call the reverse function I made it doesnt return anything. It says on my editor the address of the memory stack is being returned instead and not the string of the array I am trying to create the reverse of in my function. Can anyone offer an explanation please :(
sizeof(word) is incorrect. When the word array is passed to a function, it is passed as a pointer to the first char, so you are taking the size of the pointer (presumably 4 or 8, on 32- or 64-bit machines). Confirm by printing out the size. You need to use strlen to get the length of a string.
There are other problems with the code. For instance, you shouldn't need a nested loop to reverse a string. And sizeof(word-1) is even worse than sizeof(word). And a loop that does i-- but compares i<=0 is doomed: i will just keep getting more negative.
There are multiple problems with your reverse function. C is very different from Java. It is a lot simpler and has less features.
Sizes of arrays and strings don't propagate through parameters like you think. Your sizeof will return wrong values.
reverse is an identifier that is used twice (as function name and local variable).
You cannot return variables that are allocated on stack, because this part of stack might be destroyed after the function call returns.
You don't need two nested loops to reverse a string and the logic is also wrong.
What you probably look for is the function strlen that is available in header string.h. It will tell you the length of a string. If you want to solve it your way, you will need to know how to allocate memory for a string (and how to free it).
If you want a function that reverses strings, you can operate directly on the parameter word. It is already allocated outside the reverse function, so it will not vanish.
If you just want to output the string backwards without really reversing it, you can also output char after char from the end of the string to start by iterating from strlen(word) - 1 to 0.
Edit: Changed my reverse() function to avoid pointer arithmetic and to allow reuse of word.
Don't return const values from a function; the return value cannot be assigned to, so const doesn't make sense. Caveat: due to differences between the C and C++ type system, you should return strings as const char * if you want the code to also compile as C++.
Arrays passed as params always "decay" to a pointer.
You can't return a function-local variable, unless you allocate it on the heap using malloc(). So we need to create it in main() and pass it as a param.
Since the args are pointers, with no size info, we need to tell the function the size of the array/string: sizeof won't work.
To be a valid C string, a pointer to or array of char must end with the string termination character \0.
Must put maximum length in scanf format specifier (%99s instead of plain %s — leave one space for the string termination character \0), otherwise vulnerable to buffer overflow.
#include <stdio.h> // size_t, scanf(), printf()
#include <string.h> // strlen()
// 1. // 2. // 3. // 4.
char *reverse(char *word, char *reversed_word, size_t size);
char *reverse(char *word, char *reversed_word, size_t size)
{
size_t index = 0;
reversed_word[size] = '\0'; // 5.
while (size-- > index) {
const char temp = word[index];
reversed_word[index++] = word[size];
reversed_word[size] = temp;
}
return reversed_word;
}
int main() {
char word[100];
size_t size = 0;
printf("Enter a word: ");
scanf("%99s", word); // 6.
size = strlen(word);
printf("%s backwards is %s\n", word, reverse(word, word, size));
return 0;
}
I want to store a single char into a char array pointer and that action is in a while loop, adding in a new char every time. I strictly want to be into a variable and not printed because I am going to compare the text. Here's my code:
#include <stdio.h>
#include <string.h>
int main()
{
char c;
char *string;
while((c=getchar())!= EOF) //gets the next char in stdin and checks if stdin is not EOF.
{
char temp[2]; // I was trying to convert c, a char to temp, a const char so that I can use strcat to concernate them to string but printf returns nothing.
temp[0]=c; //assigns temp
temp[1]='\0'; //null end point
strcat(string,temp); //concernates the strings
}
printf(string); //prints out the string.
return 0;
}
I am using GCC on Debain (POSIX/UNIX operating system) and want to have windows compatability.
EDIT:
I notice some communication errors with what I actually intend to do so I will explain: I want to create a system where I can input a unlimited amount of characters and have the that input be store in a variable and read back from a variable to me, and to get around using realloc and malloc I made it so it would get the next available char until EOF. Keep in mind that I am a beginner to C (though most of you have probably guess it first) and haven't had a lot of experience memory management.
If you want unlimited amount of character input, you'll need to actively manage the size of your buffer. Which is not as hard as it sounds.
first use malloc to allocate, say, 1000 bytes.
read until this runs out.
use realloc to allocate 2000
read until this runs out.
like this:
int main(){
int buf_size=1000;
char* buf=malloc(buf_size);
char c;
int n=0;
while((c=getchar())!= EOF)
buf[n++] = c;
if(n=>buf_size-1)
{
buf_size+=1000;
buf=realloc(buf, buf_size);
}
}
buf[n] = '\0'; //add trailing 0 at the end, to make it a proper string
//do stuff with buf;
free(buf);
return 0;
}
You won't get around using malloc-oids if you want unlimited input.
You have undefined behavior.
You never set string to point anywhere, so you can't dereference that pointer.
You need something like:
char buf[1024] = "", *string = buf;
that initializes string to point to valid memory where you can write, and also sets that memory to an empty string so you can use strcat().
Note that looping strcat() like this is very inefficient, since it needs to find the end of the destination string on each call. It's better to just use pointers.
char *string;
You've declared an uninitialised variable with this statement. With some compilers, in debug this may be initialised to 0. In other compilers and a release build, you have no idea what this is pointing to in memory. You may find that when you build and run in release, your program will crash, but appears to be ok in debug. The actual behaviour is undefined.
You need to either create a variable on the stack by doing something like this
char string[100]; // assuming you're not going to receive more than 99 characters (100 including the NULL terminator)
Or, on the heap: -
char string* = (char*)malloc(100);
In which case you'll need to free the character array when you're finished with it.
Assuming you don't know how many characters the user will type, I suggest you keep track in your loop, to ensure you don't try to concatenate beyond the memory you've allocated.
Alternatively, you could limit the number of characters that a user may enter.
const int MAX_CHARS = 100;
char string[MAX_CHARS + 1]; // +1 for Null terminator
int numChars = 0;
while(numChars < MAX_CHARS) && (c=getchar())!= EOF)
{
...
++numChars;
}
As I wrote in comments, you cannot avoid malloc() / calloc() and probably realloc() for a problem such as you have described, where your program does not know until run time how much memory it will need, and must not have any predetermined limit. In addition to the memory management issues on which most of the discussion and answers have focused, however, your code has some additional issues, including:
getchar() returns type int, and to correctly handle all possible inputs you must not convert that int to char before testing against EOF. In fact, for maximum portability you need to take considerable care in converting to char, for if default char is signed, or if its representation has certain other allowed (but rare) properties, then the value returned by getchar() may exceed its maximum value, in which case direct conversion exhibits undefined behavior. (In truth, though, this issue is often ignored, usually to no ill effect in practice.)
Never pass a user-provided string to printf() as the format string. It will not do what you want for some inputs, and it can be exploited as a security vulnerability. If you want to just print a string verbatim then fputs(string, stdout) is a better choice, but you can also safely do printf("%s", string).
Here's a way to approach your problem that addresses all of these issues:
#include <stdio.h>
#include <string.h>
#include <limits.h>
#define INITIAL_BUFFER_SIZE 1024
int main()
{
char *string = malloc(INITIAL_BUFFER_SIZE);
size_t cap = INITIAL_BUFFER_SIZE;
size_t next = 0;
int c;
if (!string) {
// allocation error
return 1;
}
while ((c = getchar()) != EOF) {
if (next + 1 >= cap) {
/* insufficient space for another character plus a terminator */
cap *= 2;
string = realloc(string, cap);
if (!string) {
/* memory reallocation failure */
/* memory was leaked, but it's ok because we're about to exit */
return 1;
}
}
#if (CHAR_MAX != UCHAR_MAX)
/* char is signed; ensure defined behavior for the upcoming conversion */
if (c > CHAR_MAX) {
c -= UCHAR_MAX;
#if ((CHAR_MAX != (UCHAR_MAX >> 1)) || (CHAR_MAX == (-1 * CHAR_MIN)))
/* char's representation has more padding bits than unsigned
char's, or it is represented as sign/magnitude or ones' complement */
if (c < CHAR_MIN) {
/* not representable as a char */
return 1;
}
#endif
}
#endif
string[next++] = (char) c;
}
string[next] = '\0';
fputs(string, stdout);
return 0;
}