I have a problem with the set_ccs function. I cannot take elements from user. How can i fix that?
int main(){
char *ccs;
*ccs =(char*)malloc(sizeof(char) * 80);//i have to use dynamic memory allocation
printf("Enter CCS: ");
set_ccs(&ccs);
free(ccs);
return 0;
}
int set_ccs(char **ccs){
int i = 0;
scanf("%s",*ccs);//Is it better to use fgets? Because scanf seems to count 'enter'
while(*ccs!='\0'){
ccs++;
i++;
}
printf("Length of sequence : %d\n",i);//It always return 3
printf("%s",ccs); //with weird elements
return i;
}
Thanks already.
In addition to unwinds answer that you should just use
char *ccs;
ccs = malloc(80);
You should make the function set_ccs() accept a pointer:
int set_ccs(char *ccs)
And call it like this from your main:
set_ccs(css);
Then in your function you can use scanf() like so:
scanf("%s", css);
Now you if you want to check for '\0', it is good practice to initialize your "string" to 0 before you use it. You can do that with calloc(80) instead of malloc(80).
If you need to have the pointer to pointer (char **ccs), you have to make a double pointer in your main, check this code:
int main(){
char *ccs;
char **ccs2; //a pointer to a pointer
ccs = calloc(80); //i have to use dynamic memory allocation
ccs2 = &ccs; //pass the address of the pointer to the double pointer
printf("Enter CCS: ");
set_ccs(ccs2); //pass the double pointer
free(ccs);
return 0;
}
int set_ccs(char **ccs){
int i = 0;
scanf("%s", *ccs);
char *c = *ccs; //copy to make increments
while(*c != '\0'){
c++;
i++;
}
printf("Length of sequence : %d\n", i);
printf("%s", *ccs);
return i;
}
This:
char *ccs;
*ccs =(char*)malloc(sizeof(char) * 80);
Is wrong, and there is no sane compiler that will accept it. You're shoving a pointer into a char, and it certainly won't fit.
It should just be:
ccs = malloc(80);
There's no need to scale by sizeof (char), that is always 1.
Also, please don't cast the return value of malloc() in C.
Related
This question already has answers here:
Returning an array using C
(8 answers)
Closed 3 years ago.
I want the function lch() to return a string that can be used outside the function.
This is the code I have written, but it does not seem to work:
char *lch(char *ch,int n){
char c[n];
for(int i=0;i<n;i++){
c[i] = *ch;
}
puts(c); // check output string inside function
return c;
}
char str[100],*p;
main(){
p = lch("a",20);
puts(p); // check output outside function
}
I am confused with strings and how they should be passed to functions.
I want the output string to become the same on both calls to puts().
What should I do?
That is the result of the code above:
aaaaaaaaaaaaaaaaaaaa // inside the function
¢ÞêÊ· // outside the function
First of all, returning locally allocated storage will not work. You have to return dynamically allocated storage, and with a proper size to accommodate the null-terminator:
char *c = malloc(n+1);
/* ... */
/* end of program: */
free(p);
Second, you want to pass a character to your function, not a string:
char *lch(char ch,int n){
/* ... */
c[i] = ch;
/* ... */
p = lch('a', 20);
Third, you have to null-terminate your string:
int i;
for(i=0;i<n;i++){
c[i] = ch;
}
ch[i] = '\0';
puts(c); //check output string inside function
Here's the dynamically-allocated storage approach:
#include <stdlib.h>
#include <stdio.h>
char *lch(char ch,int n){
char *c = malloc(n+1);
int i;
for(i=0;i<n;i++){
c[i] = ch;
}
c[i] = '\0';
puts(c); //check output string inside function
return c;
}
char *p;
int main(void){
p = lch('a',20);
puts(p); //check output outside function
free(p);
return 0;
}
This also fixes the declaration and return type of main (main is supposed to be int main(void) or int main(int argc, char **argv)), removes the unneeded variable str, and adds needed #includes.
The reason your code does not do what you expect it to do is because the string in the function is allocated on the stack, which means that its memory is cleaned as soon as you exit the function.
That means the pointer p points to garbage value after the call to lch().
Also, you can not declare an array of size that is not a constant value, so the line:
char c[n];
would simply not work.
To solve this, you will need to dynamically allocate the string using malloc(3) :
char* lch(char ch, int n)
{
char * c;
/* Allocate n bytes of memory for the string */
c = malloc(n + 1);
if (NULL == c)
{
/* Failed to allocate memory, exit the function */
return c;
}
for(int i = 0; i < n; i++)
{
c[i] = ch;
}
/* Add a terminating null byte (to make it a string) */
c[i] = '\0';
puts(c);
return c;
}
int main(void)
{
char * p;
p = lch('a', 20);
puts(p);
/* Free the string from the memory */
free(p);
return 0;
}
I added a few fixes to the code but the main thing you need to look at is the use of malloc(3).
I dynamically allocated n+1 bytes of memory for the string, then wrote the data into the string (plus a '\0'), and when the function exits the memory will still be available and wont be corrupted.
The call to free is needed to free the memory we have allocated.
You can read more about malloc(3) here: https://linux.die.net/man/3/malloc
I have been looking on internet for this and so far i just found a lot of questions for specific answer and not a general one.
i am kind of rusty on C. And i want to make a function that will return an array of char.
this is what i got and is not working. basically a way to convert a byte array to an array of chars to do atoi later..
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *get_char(int my_byte[], int packetsize)
{
char *array_char=(char *) malloc(sizeof(char)*10); //trying this but didnt work
// char array_char[10]; //i had it like this before(was told to do it)
for(int i=0;i<10;i++)
{
array_char[i]=my_byte[i]+0;
}
return array_char;
}
int main()
{
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp;
char data;
temp=get_char(byte_array,10);
data=*temp;
printf("String point %s ",data);
}
Two fixes:
As you want to convert to char, then
array_char[i]=my_byte[i]+0; should be array_char[i]=my_byte[i]+'0'; Note '0' is character (that will be converted to int) instead of numeric 0 (which doesn't do anything).
Also you must free temp pointer in main as that memory is dynamically allocated in get_char() function.
Edit: just notice another issue in your get_char()
char *array_char=(char *) malloc(sizeof(char)*10);
should be
char *array_char= malloc(sizeof(char)*(packetsize+1));
After the for loop, ensure the buffer is NUL-terminated:
array_char[packetsize] = '\0';
Notice that your packetsize is never used - you should get some compiler warning about it. It's bad to hard code 10 in your malloc - it's actually the whole idea of parsing the packetsize as a parameter - so use it properly.
You need to watch out for these things:
You need to add a null-terminating character at the end of *array_char, otherwise using this pointer allocated from the heap will cause undefined behaviour.
You can simply allocate *array_char like this:
char *array_char = malloc(packetsize+1);
As sizeof(char) is 1, and +1 for trailing nullbyte.
You also don't need to cast return of malloc().
Instead of passing 10 as packetsize to get_char(), you should pass this size as sizeof(arr) / sizeof(arr[0], which is the calculated size of the array. This can be a size_t variable declared somewhere or even a macro.
malloc() needs to be checked, as it can return NULL if unsuccessful.
You need to free() temp at some point in the program.
array_char[i]=my_byte[i]+0; needs to be array_char[i]=my_byte[i]+'0'; instead, as '0' is the ascii code for a zero character.
char data needs to be char *data, as temp is a pointer.
If you compile with -Wall -Wextra, you will see that this line:
data=*temp;
Is dangerous, and will trigger warnings of making pointers from integers without a cast. It will most likely lead to a segmentation fault. If temp and data are both pointers, then you can simply use:
data=temp;
Which sets data to the address of temp. Sometimes this is written as data = &(*temp);, but this is harder to read. Although their is no need for data, and using temp alone should be fine.
Your code can then look like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
char *get_char(int my_byte[], size_t packetsize) {
char *array_char = malloc(packetsize+1);
const char ascii = '0';
size_t i;
if (!array_char) {
printf("Cannot allocate %zu bytes\n", packetsize+1);
exit(EXIT_FAILURE);
}
for(i = 0; i < packetsize; i++) {
array_char[i] = my_byte[i] + ascii;
}
array_char[i] = '\0'; /* or array_char[packetsize] = '\0' */
return array_char;
}
int main(void) {
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp, *data;
temp = get_char(byte_array, ARRAYSIZE(byte_array));
data = temp;
printf("String point %s\n", data);
printf("String converted into number = %d\n", atoi(data));
free(temp);
temp = NULL;
return 0;
}
You can also look into strtol, which is better than using atoi() in terms of error checking.
It is Not Wise Idea to Return a Array From A Function. So how to return a string then? As most of libc functions use we can use some thing like that (i.e) passing a buffer along with our input and expect function to use output buffer to give us result.
Some issue to take care while coding
write your logic first.
try to use available functions from libc.
while dealing with byte data/binary data be take precaution of buffer overflow.
don't allocate in a function and de-allocate in another function.
Below is Example of your code with modification.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <stdint.h>
int get_char(uint8_t my_byte[], int packetsize, char *buffer, int max_buffer)
{
int byte_itr, buf_itr;
char temp_buf[16]={0x00};
for(byte_itr=0, buf_itr=0; byte_itr<packetsize && max_buffer > buf_itr; byte_itr++)
{
memset(temp_buf, 0x00, sizeof(temp_buf));
char temp_ch = my_byte[byte_itr];
snprintf(temp_buf, sizeof(temp_buf), "%d", temp_ch);
if( buf_itr+strlen(temp_buf) >=max_buffer){
break;
}else{
buf_itr += strlen(temp_buf);
strcat(buffer, temp_buf);
if(byte_itr+1 < packetsize){
strcat(buffer, ",");
buf_itr += 1;
}
}
}
return buf_itr;
}
int main()
{
uint8_t byte_array[]={1,2,3,4,5,6,7,8,9,0};
char char_array[32]={0x00};
int len = get_char(byte_array, 10, char_array, sizeof(char_array));
printf("String point %s : len %d\n", char_array, len);
}
NOTE:
when length return and size of output buffer same then buffer full condition happened.
I am having some memory issues with printing hex in the following format: \xAA\xAB\xDC using my encryption routine.
I did some modifications, using snprintf() and strcat() in an attempt to fix the output and it worked to some degree.
This is the function I originally started out with, which is probably better than my modified version.
char *encrypt(char key, const char *a) {
char *output = malloc(strlen(a)+1);
bzero(output, strlen(a)+1);
strcpy(output, a);
char *tmp = output;
int i;
for (i = 0; tmp[i] != 0; i++) {
tmp[i] = key ^ tmp[i];
}
return output;
}
My current progress is as follows:
char *encrypt(char key, const char *a)
{
char buf[256];
char *tmp = a;
int i;
int *k;
for (i = 0; tmp[i] != 0; i++)
{
char temp[10];
k = key ^ tmp[i];
snprintf(temp, sizeof(temp), "\\x%s", k);
strcat(buf, temp);
}
return buf;
}
int main(int argc, char **argv)
{
if (argv[1] == NULL){
printf("Usage: %s <string>\n", argv[0]);
}
else printf("Encrypted string: %s\n", encrypt(0xEB, argv[1]));
return 0;
}
If anyone could point me in the right direction on how to fix the memory issue, and if the code can be improved I would appreciate that a lot.
The primary issue, in your code, buf is local to the function encrypt(). So you may not return the array from the function. Once the function finishes, the array will cease to exist and the returned address will be invalid. If the returned value is ued in the caller, it will invoke undefined behavior.
You need to define buf as a pointer and allocate dynamic memory using malloc() or family. Also, you need to free() the memory, once the usage is over.
That said,
you have defined k to be a pointer but did not allocate memory to it.
k = key ^ tmp[i]; seems meaningless, maybe you meant *k = key ^ tmp[i];
%s expects a pointer to char array (null-terminated) as argument. From that point, snprintf(temp, sizeof(temp), "\\x%s", k); also looks wrong. What you need is snprintf(temp, sizeof(temp), "\\x%d", *k); to print the int value.
Instead of:
int *k;
k = key ^ tmp[i];
snprintf(temp, sizeof(temp), "\\x%s", k);
use this:
unsigned char k;
k = key ^ tmp[i];
snprintf(temp, sizeof temp, "\\x%02X", k);
Note that you also have other changes to make regarding buf. Firstly you never initialize it, so you are appending to junk. And you never check that you didn't overflow it.
Also you attempt to return this from a function, however, since it is a local variable, it ceases to exist when the function returns.
See this thread for some suggestions of how to get freshly-written string out of a function. You could use malloc(256) in the same vein as your first attempt (and remember to replace sizeof buf with the mallocated length, in the snprintf call).
It'd be more robust to use unsigned char instead of char for both the key and the message. An example of the issues is that on x86 or x64, char has a range of -128 to 127 so when you supply 0xEB (i.e. 235) this is an out-of-range assignment which is not well-defined.
But on common systems you will get away with using char because they tend to define out-of-range assignment by using 2's complement and truncating excess bits, which works in your situation.
I have a problem with assigning specific pointer to another char sequence(string);
#include<stdio.h>
void setInformations(char *informations[], char *contests_name[]);
int main(void) {
char *informations[]={"","","",""};
char *contests_name[]={"cycle_race","swim","running race"};
int totalTime=0;
setInformations(informations,contests_name);
getch();
return 0;
}
void setInformations(char *informations[], char *contests_name[]) {
printf("Competitor's name: ");
scanf("%s",*informations[0]);
printf("%s",informations[0]);
}
I know that the problem is assigning string to pointer of type char. How can I replace this (strcpy?)
Take the * out of the scanf:
scanf ("%s", informations[0]);
...and allocate space for the informations array
char* informations[NUMBER_OF_INFORMATIONS][MAX_NAME_LENGTH] = {{'\0'}};
so scanf will have room to put in the info.
here : scanf("%s",*informations[0]);, you are trying to write in a read-only memory.
So you have to allocate the memory in the main :
int stringSize = 30; // example of length
char* informations[3];
informations[0] = malloc(stringSize);
informations[1] = malloc(stringSize);
informations[2] = malloc(stringSize);
//initialyse the strings to "" :
informations[0][0] = '\0';
informations[1][0] ='\0';
informations[2][0] ='\0';
in setInformations(, you have to delete the * to give scanf the adress of the memory where to write). correct syntax : scanf("%s",informations[0]);
this is the rough idea of what I am trying to do:
I want the pointer in main to point to the word I just in my function.
my actual code is very long so please excuse this format.
main()
{
char *word;
int lim 256;
*word = function(word,lim)//I am not returning the address back only the first letter
}
function(word,lim)
{
//memory allocation
//getting word
//reset address
return(*word);//I am passing the correct address here
}
char* allocate_word(int lim)
{
// malloc returns a "void*" which you cast to "char*" and
//return to the "word" variable in "main()"
// We need to allocate "lim" number of "char"s.
// So we need to multiply the number of "char"s we need by
//the number of bytes each "char" needs which is given by "sizeof(char)".
return (char*)malloc(lim*sizeof(char));
}
int main()
{
char *word;
// You need to use "=" to assign values to variables.
const int lim = 256;
word = allocate_word(lim);
// Deallocate!
free(word);
return 0;
}
Functions used in the sample code above:
malloc
free
This seems like a decent tutorial:
C Tutorial – The functions malloc and free
char* func()
{
return (char*)malloc(256);
}
int main()
{
char* word = func();
free(word);
return 0;
}