This code finds the next word in the string.
For example
given an input of " my cake" the function should return "my cake". as the expected output
If I use return then the output is (null), but I use printf then the code works
I would like to know how to get the expected output using return.
#include <stdio.h>
int main()
{
char* str[1000];
printf("enter:");
fgets(str,1000,stdin);
printf("%s",find_word_start(str));
}
char* find_word_start(char* str){
char* result[1000];
int c = 0, d = 0;
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){
result[d++] = str[c++];
if(str[c]==' ') {
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d] = '\0';
//print or return char?
return result;
}
char* result[1000]; creates an array of 1000 pointers. That's wrong in a number of ways.
You want a block of 1000 chars, not pointers.
Actually, 1000 is not the number of characters you want. You usually want a smaller number, but you could also want a larger number.
You don't want to store the result in automatically allocated memory, because that will be freed as soon as you exit the function. Use malloc (or something that does a malloc such as strdup).
Fix:
// Returns a copy that needs to be freed.
char* find_word_start(const char* src) {
while (*src == ' ')
++src;
size_t len = 0;
while (str[len] != '\0')
++len;
++len; // Include NUL
result = malloc(len);
char* dst = result;
while (len--)
*(dst++) = *(src++);
return result;
}
Well, I was avoiding using string functions above like you did, but they greatly simplify the solution.
// Returns a copy that needs to be freed.
char* find_word_start(const char* src) {
while (*src == ' ')
++src;
return strdup(src);
}
That said, since you return the tail end of the string, you could simply return a pointer into the existing string.
// Returns a pointer into the provided string.
const char* find_word_start(const char* str) {
while (*str == ' ')
++str;
return str;
}
The following line allocates memory space in the stack but after the function ends everything is gone:
char result[1000];
You need to allocate memory in the heap like that:
char *result = malloc(sizeof(char) *1000);
Note: don't forget to free that memory space by free function.
Related
My goal in the code is to parse some sort of input into words regarding all spaces but at the same time use those spaces to signify a change in words. The logic here is that anytime it encounters a space it loops until there is no longer a space character and then when it encounters a word it loops until it encounters a space character or a '\0' and meanwhile puts each character into one index of an array inside arrays in the 2d array. Then before the while loop continues again it indexes to the next array.
I'm almost certain the logic is implemented well enough for it to work but I get this weird output listed below I've had the same problem before when messing with pointers and whatnot but I just can't get this to work no matter what I do. Any ideas as to why I'm genuinely curious about the reason behind why?
#include <stdio.h>
#include <stdlib.h>
void print_mat(char **arry, int y, int x){
for(int i=0;i<y;i++){
for(int j=0;j<x;j++){
printf("%c",arry[i][j]);
}
printf("\n");
}
}
char **parse(char *str)
{
char **parsed=(char**)malloc(sizeof(10*sizeof(char*)));
for(int i=0;i<10;i++){
parsed[i]=(char*)malloc(200*sizeof(char));
}
char **pointer = parsed;
while(*str!='\0'){
if(*str==32)
{
while(*str==32 && *str!='\0'){
str++;
}
}
while(*str!=32 && *str!='\0'){
(*pointer) = (str);
(*pointer)++;
str++;
}
pointer++;
}
return parsed;
}
int main(){
char str[] = "command -par1 -par2 thething";
char**point=parse(str);
print_mat(point,10,200);
return 0;
}
-par1 -par2 thethingUP%�W���U�6o� X%��U�v;,���UP%���cNjW��]A�aW�Ӹto�8so�z�
-par2 thethingUP%�W���U�6o� X%��U�v;,���UP%���cNjW��]A�aW�Ӹto�8so�z�
thethingUP%�W���U�6o� X%��U�v;,���UP%���cNjW��]A�aW�Ӹto�8so�z�
UP%�W���U�6o� X%��U�v;,���UP%���cNjW��]A�aW�Ӹto�8so�z�
I also tried to simply index the 2d array but to no avail
char **parse(char *str)
{
int i, j;
i=0;
j=0;
char **parsed=(char**)malloc(sizeof(10*sizeof(char*)));
for(int i=0;i<10;i++){
parsed[i]=(char*)malloc(200*sizeof(char));
}
while(*str!='\0'){
i=0;
if(*str==32)
{
while(*str==32 && *str!='\0'){
str++;
}
}
while(*str!=32 && *str!='\0'){
parsed[j][i] = (*str);
i++;
str++;
}
j++;
}
return parsed;
}
Output:
command�&�v�U`'�v�U0(�v�U)�v�U�)�v�U
-par1
-par2
thething
makefile:5: recipe for target 'build' failed
make: *** [build] Segmentation fault (core dumped)
A couple of problems in your code:
Your program is leaking memory.
Your program is accessing memory which it does not own and this is UB.
Lets discuss them one by one -
First problem - Memory leak:
Check this part of parse() function:
while(*str!=32 && *str!='\0'){
(*pointer) = (str);
In the first iteration of outer while loop, the *pointer will give you first member of parsed array i.e. parsed[0], which is a pointer to char. Note that you are dynamically allocating memory to parsed[0], parsed[1]... parsed[9] pointers in parse() before the outer while loop. In the inner while loop you are pointing them to str. Hence, they will loose the dynamically allocated memory reference and leading to memory leak.
Second problem - Accessing memory which it does not own:
As stated above that the pointers parsed[0], parsed[1] etc. will point to whatever was the current value of str in the inner while loop of parse() function. That means, the pointers parsed[0], parsed[1] etc. will point to some element of array str (defined in main()). In the print_mat() function, you are passing 200 and accessing every pointer of array arry from 0 to 199 index. Since, the arry pointers are pointing to str array whose size is 29, that means, your program is accessing memory (array) beyond its size which is UB.
Lets fix these problem in your code without making much of changes:
For memory leak:
Instead of pointing the pointers to str, assign characters of str to the allocated memory, like this:
int i = 0;
while(*str!=32 && *str!='\0'){
(*pointer)[i++] = (*str);
str++;
}
For accessing memory which it does not own:
A point that you should remember:
In C, strings are actually one-dimensional array of characters terminated by a null character \0.
First of all, empty the strings after dynamically allocating memory to them so that you can identify the unused pointers while printing them:
for(int i=0;i<10;i++){
parsed[i]=(char*)malloc(200*sizeof(char));
parsed[i][0] = '\0';
}
Terminate all string in with null terminator character after writing word to parsed array pointers:
int i = 0;
while(*str!=32 && *str!='\0'){
(*pointer)[i++] = (*str);
str++;
}
// Add null terminator
(*pointer)[i] = '\0';
In the print_mat(), make sure once you hit the null terminator character, don't read beyond it. Modify the condition of inner for loop:
for(int j = 0; (j < x) && (arry[i][j] != '\0'); j++){
printf("%c",arry[i][j]);
You don't need to print the strings character by character, you can simply use %s format specifier to print a string, like this -
for (int i = 0;i < y; i++) {
if (arry[i][0] != '\0') {
printf ("%s\n", arry[i]);
}
}
With the above suggested changes (which are the minimal changes required in your program to work it properly), your code will look like this:
#include <stdio.h>
#include <stdlib.h>
void print_mat (char **arry, int y) {
for (int i = 0; i < y; i++) {
if (arry[i][0] != '\0') {
printf ("%s\n", arry[i]);
}
}
}
char **parse(char *str) {
char **parsed = (char**)malloc(sizeof(10*sizeof(char*)));
// check malloc return
for(int i = 0; i < 10; i++){
parsed[i] = (char*)malloc(200*sizeof(char));
// check malloc return
parsed[i][0] = '\0';
}
char **pointer = parsed;
while (*str != '\0') {
if(*str == 32) {
while(*str==32 && *str!='\0') {
str++;
}
}
int i = 0;
while (*str != 32 && *str != '\0') {
(*pointer)[i++] = (*str);
str++;
}
(*pointer)[i] = '\0';
pointer++;
}
return parsed;
}
int main (void) {
char str[] = "command -par1 -par2 thething";
char **point = parse(str);
print_mat (point, 10);
// free the dynamically allocate memory
return 0;
}
Output:
command
-par1
-par2
thething
There is a lot improvements can be done in your code implementation, for e.g. -
As I have shown above, you can use %s format specifier instead of printing string character by character etc.. I am leaving it up to you to identify those changes and modify your program.
Allocate memory to a parsed array pointer only where there is a word in str.
Instead of allocating memory of fixed size (i.e. 200) to parsed array pointers, allocate memory of size of word only.
Few suggestions:
Always check the return value of function like malloc.
Make sure to free the dynamically allocated memory once your program done with it.
You can achieve what you want in a simpler way.
First, define a function that checks if a character (separator) is present in a list of characters (separators):
// Returns true if c is found in a list of separators, false otherwise.
bool belongs(const char c, const char *list)
{
for (const char *p = list; *p; ++p)
if (*p == c) return true;
return false;
}
Then, define a function that splits a given string into tokens, separated by one or more separators:
// Splits a string into into tokens, separated by one of the separators in sep
bool split(const char *s, const char *sep, char **tokens, size_t *ntokens, const size_t maxtokens)
{
// Start with zero tokens.
*ntokens = 0;
const char *start = s, *end = s;
for (const char *p = s; /*no condtition*/; ++p) {
// Can no longer hold more tokens? Exit.
if (*ntokens == maxtokens)
return false;
// Not a token? Continue looping.
if (*p && !belongs(*p, sep))
continue;
// Found a token: calculate its length.
size_t tlength = p - start;
// Empty token?
if (tlength == 0) {
// And reached the end of string? Break.
if (!*p) break;
// Not the end of string? Skip it.
++start;
continue;
}
// Attempt to allocate memory.
char *token = malloc(sizeof(*token) * (tlength + 1));
// Failed? Exit.
if (!token)
return false;
// Copy the token.
strncpy(token, start, tlength+1);
token[tlength] = '\0';
// Put it in tokens array.
tokens[*ntokens] = token;
// Update the number of tokens.
*ntokens += 1;
// Reached the end of string? Break.
if (!*p) break;
// There is more to parse. Set the start to the next char.
start = p + 1;
}
return true;
}
Call it like this:
int main(void)
{
char command[] = "command -par1 -par2 thing";
const size_t maxtokens = 10;
char **tokens = malloc(sizeof *tokens * maxtokens);
if (!tokens) return 1;
size_t ntokens = 0;
split(command, " ", tokens, &ntokens, maxtokens);
// Print all tokens.
printf("Number of tokens = %ld\n", ntokens);
for (size_t i = 0; i < ntokens; ++i)
printf("%s\n", tokens[i]);
// Release memory when done.
for (size_t i = 0; i < ntokens; ++i)
free(tokens[i]);
free(tokens);
}
Output:
Number of tokens = 4
command
-par1
-par2
thing
I'm trying to implement a trim function in C, and in doing so I'm using two sub-functions, ltrim and rtrim. I was wondering if I'm "leaking" memory somehow by calling malloc so much. If so, where should I be freeing the memory or altering how the malloc is called?
Ltrim:
char * rtrim(char * string) {
size_t slen = strlen(string);
char * modified_string = malloc(slen + 1);
strcpy(modified_string, string);
for (int i=slen-1; i>0 ;i--) {
if (string[i] == ' ' || string[i] == '\t')
modified_string[i] = '\0';
else
break;
}
return modified_string;
}
Rtrim:
char * ltrim(char * string) {
char c;
int start_index = -1;
char * modified_string = malloc(strlen(string) + 1);
for (int i=0; (c=string[i]) != '\0'; i++) {
if ((c == ' ' || c == '\t') && (start_index == -1)) {
;
} else {
if (start_index == -1) start_index = i;
modified_string[i - start_index] = c;
}
}
return modified_string;
}
Trim:
char * trim(char * string) {
char * string1 = ltrim(string);
char * string2 = rtrim(string1);
return string2;
}
Main:
int main(int argc, char *argv[]) {
char * new_str = " howlin ";
printf("Original: \"%s\" | RTrimmed: \"%s\"\n", new_str, rtrim(new_str));
printf("Original: \"%s\" | LTrimmed: \"%s\"\n", new_str, ltrim(new_str));
printf("Original: \"%s\" | Trimmed: \"%s\"\n", new_str, trim(new_str));
return 0;
}
Your functions aren't technically leaking memory, but they're making it really easy for the calling code to leak memory. Case in point: your sample main function leaked the buffers returned by the three calls to ltrim/rtrim, and your trim function leaked string1.
Instead, consider how these can be simplified. ltrim doesn't need to allocate memory at all. It can simply return a pointer to the first non-space character in the input string. rtrim isn't so easy, though.
One way to avoid the memory problems entirely is to have the functions modify the input string. Your output is never longer than the input, so you'll always have enough buffer available. rtrim would simply replace the first whitespace character at the end of the string with '\0', and ltrim would memmove() using a pointer to the first non-whitespace character. Modifying the strings in place means that the caller knows that they're responsible for making copies, allocating buffers, etc. and makes it harder to accidentally leak memory.
If so, where should I be freeing the memory or altering how the malloc is called?
Consider re-architecting your helper functions ltrim(), rtrim() without malloc() and let the calling code handle allocations.
// Return beginning of trimmed string.
const char *ltrim(const char * string) {
while (isspace((unsigned char) *string) {
string++;
}
return string;
}
// Return end of "trimmed" string.
const char *rtrim(const char * string) {
// find first non-space
const char *non_space = string;
while (isspace((unsigned char) **non_space) {
*non_space++;
}
if (*non_space) {
// Quickly go to the null character.
string = non_space + strlen(*non_space);
// While the character to the "left" is a space, backup.
// Here we know there is a non-white-space somewhere to the left,
// so loop will end with only a `isspace()` test.
while (isspace((unsigned char) string[-1]) {
string--;
}
}
return string;
}
Now armed with these helper functions ....
char * trim_alloc(const char * string) {
string = ltrim(string);
const char *end = rtrim(string);
size_t length = end - string;
char *copy = malloc(length + 1);
if (copy) {
memcpy(copy, string, length);
copy[length] = '\0';
}
return copy;
}
Was is speedy about rtrim is that each of its 3 loops (while, strlen, while) are each only testing for one condition and not 2 like "isspace && not null_character". This approach works best with sizable strings with a small amount of right trimming.
My str_split function returns (or at least I think it does) a char** - so a list of strings essentially. It takes a string parameter, a char delimiter to split the string on, and a pointer to an int to place the number of strings detected.
The way I did it, which may be highly inefficient, is to make a buffer of x length (x = length of string), then copy element of string until we reach delimiter, or '\0' character. Then it copies the buffer to the char**, which is what we are returning (and has been malloced earlier, and can be freed from main()), then clears the buffer and repeats.
Although the algorithm may be iffy, the logic is definitely sound as my debug code (the _D) shows it's being copied correctly. The part I'm stuck on is when I make a char** in main, set it equal to my function. It doesn't return null, crash the program, or throw any errors, but it doesn't quite seem to work either. I'm assuming this is what is meant be the term Undefined Behavior.
Anyhow, after a lot of thinking (I'm new to all this) I tried something else, which you will see in the code, currently commented out. When I use malloc to copy the buffer to a new string, and pass that copy to aforementioned char**, it seems to work perfectly. HOWEVER, this creates an obvious memory leak as I can't free it later... so I'm lost.
When I did some research I found this post, which follows the idea of my code almost exactly and works, meaning there isn't an inherent problem with the format (return value, parameters, etc) of my str_split function. YET his only has 1 malloc, for the char**, and works just fine.
Below is my code. I've been trying to figure this out and it's scrambling my brain, so I'd really appreciate help!! Sorry in advance for the 'i', 'b', 'c' it's a bit convoluted I know.
Edit: should mention that with the following code,
ret[c] = buffer;
printf("Content of ret[%i] = \"%s\" \n", c, ret[c]);
it does indeed print correctly. It's only when I call the function from main that it gets weird. I'm guessing it's because it's out of scope ?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEBUG
#ifdef DEBUG
#define _D if (1)
#else
#define _D if (0)
#endif
char **str_split(char[], char, int*);
int count_char(char[], char);
int main(void) {
int num_strings = 0;
char **result = str_split("Helo_World_poopy_pants", '_', &num_strings);
if (result == NULL) {
printf("result is NULL\n");
return 0;
}
if (num_strings > 0) {
for (int i = 0; i < num_strings; i++) {
printf("\"%s\" \n", result[i]);
}
}
free(result);
return 0;
}
char **str_split(char string[], char delim, int *num_strings) {
int num_delim = count_char(string, delim);
*num_strings = num_delim + 1;
if (*num_strings < 2) {
return NULL;
}
//return value
char **ret = malloc((*num_strings) * sizeof(char*));
if (ret == NULL) {
_D printf("ret is null.\n");
return NULL;
}
int slen = strlen(string);
char buffer[slen];
/* b is the buffer index, c is the index for **ret */
int b = 0, c = 0;
for (int i = 0; i < slen + 1; i++) {
char cur = string[i];
if (cur == delim || cur == '\0') {
_D printf("Copying content of buffer to ret[%i]\n", c);
//char *tmp = malloc(sizeof(char) * slen + 1);
//strcpy(tmp, buffer);
//ret[c] = tmp;
ret[c] = buffer;
_D printf("Content of ret[%i] = \"%s\" \n", c, ret[c]);
//free(tmp);
c++;
b = 0;
continue;
}
//otherwise
_D printf("{%i} Copying char[%c] to index [%i] of buffer\n", c, cur, b);
buffer[b] = cur;
buffer[b+1] = '\0'; /* extend the null char */
b++;
_D printf("Buffer is now equal to: \"%s\"\n", buffer);
}
return ret;
}
int count_char(char base[], char c) {
int count = 0;
int i = 0;
while (base[i] != '\0') {
if (base[i++] == c) {
count++;
}
}
_D printf("Found %i occurence(s) of '%c'\n", count, c);
return count;
}
You are storing pointers to a buffer that exists on the stack. Using those pointers after returning from the function results in undefined behavior.
To get around this requires one of the following:
Allow the function to modify the input string (i.e. replace delimiters with null-terminator characters) and return pointers into it. The caller must be aware that this can happen. Note that supplying a string literal as you are doing here is illegal in C, so you would instead need to do:
char my_string[] = "Helo_World_poopy_pants";
char **result = str_split(my_string, '_', &num_strings);
In this case, the function should also make it clear that a string literal is not acceptable input, and define its first parameter as const char* string (instead of char string[]).
Allow the function to make a copy of the string and then modify the copy. You have expressed concerns about leaking this memory, but that concern is mostly to do with your program's design rather than a necessity.
It's perfectly valid to duplicate each string individually and then clean them all up later. The main issue is that it's inconvenient, and also slightly pointless.
Let's address the second point. You have several options, but if you insist that the result be easily cleaned-up with a call to free, then try this strategy:
When you allocate the pointer array, also make it large enough to hold a copy of the string:
// Allocate storage for `num_strings` pointers, plus a copy of the original string,
// then copy the string into memory immediately following the pointer storage.
char **ret = malloc((*num_strings) * sizeof(char*) + strlen(string) + 1);
char *buffer = (char*)&ret[*num_strings];
strcpy(buffer, string);
Now, do all your string operations on buffer. For example:
// Extract all delimited substrings. Here, buffer will always point at the
// current substring, and p will search for the delimiter. Once found,
// the substring is terminated, its pointer appended to the substring array,
// and then buffer is pointed at the next substring, if any.
int c = 0;
for(char *p = buffer; *buffer; ++p)
{
if (*p == delim || !*p) {
char *next = p;
if (*p) {
*p = '\0';
++next;
}
ret[c++] = buffer;
buffer = next;
}
}
When you need to clean up, it's just a single call to free, because everything was stored together.
The string pointers you store into the res with ret[c] = buffer; array point to an automatic array that goes out of scope when the function returns. The code subsequently has undefined behavior. You should allocate these strings with strdup().
Note also that it might not be appropriate to return NULL when the string does not contain a separator. Why not return an array with a single string?
Here is a simpler implementation:
#include <stdlib.h>
char **str_split(const char *string, char delim, int *num_strings) {
int i, n, from, to;
char **res;
for (n = 1, i = 0; string[i]; i++)
n += (string[i] == delim);
*num_strings = 0;
res = malloc(sizeof(*res) * n);
if (res == NULL)
return NULL;
for (i = from = to = 0;; from = to + 1) {
for (to = from; string[to] != delim && string[to] != '\0'; to++)
continue;
res[i] = malloc(to - from + 1);
if (res[i] == NULL) {
/* allocation failure: free memory allocated so far */
while (i > 0)
free(res[--i]);
free(res);
return NULL;
}
memcpy(res[i], string + from, to - from);
res[i][to - from] = '\0';
i++;
if (string[to] == '\0')
break;
}
*num_strings = n;
return res;
}
I want to read input from user using C program. I don't want to use array like,
char names[50];
because if the user gives string of length 10, then the remaining spaces are wasted.
If I use character pointer like,
char *names;
then I need to allocate memory for that in such a way of,
names = (char *)malloc(20 * sizeof(char));
In this case also, there is a possibility of memory wastage.
So, what I need is to dynamically allocate memory for a string which is of exactly same as the length of the string.
Lets assume,
If the user input is "stackoverflow", then the memory allocated should be of 14 (i.e. Length of the string = 13 and 1 additional space for '\0').
How could I achieve this?
Read one character at a time (using getc(stdin)) and grow the string (realloc) as you go.
Here's a function I wrote some time ago. Note it's intended only for text input.
char *getln()
{
char *line = NULL, *tmp = NULL;
size_t size = 0, index = 0;
int ch = EOF;
while (ch) {
ch = getc(stdin);
/* Check if we need to stop. */
if (ch == EOF || ch == '\n')
ch = 0;
/* Check if we need to expand. */
if (size <= index) {
size += CHUNK;
tmp = realloc(line, size);
if (!tmp) {
free(line);
line = NULL;
break;
}
line = tmp;
}
/* Actually store the thing. */
line[index++] = ch;
}
return line;
}
You could have an array that starts out with 10 elements. Read input character by character. If it goes over, realloc another 5 more. Not the best, but then you can free the other space later.
You can also use a regular expression, for instance the following piece of code:
char *names
scanf("%m[^\n]", &names)
will get the whole line from stdin, allocating dynamically the amount of space that it takes. After that, of course, you have to free names.
If you ought to spare memory, read char by char and realloc each time. Performance will die, but you'll spare this 10 bytes.
Another good tradeoff is to read in a function (using a local variable) then copying. So the big buffer will be function scoped.
Below is the code for creating dynamic string :
void main()
{
char *str, c;
int i = 0, j = 1;
str = (char*)malloc(sizeof(char));
printf("Enter String : ");
while (c != '\n') {
// read the input from keyboard standard input
c = getc(stdin);
// re-allocate (resize) memory for character read to be stored
str = (char*)realloc(str, j * sizeof(char));
// store read character by making pointer point to c
str[i] = c;
i++;
j++;
}
str[i] = '\0'; // at the end append null character to mark end of string
printf("\nThe entered string is : %s", str);
free(str); // important step the pointer declared must be made free
}
First, define a new function to read the input (according to the structure of your input) and store the string, which means the memory in stack used. Set the length of string to be enough for your input.
Second, use strlen to measure the exact used length of string stored before, and malloc to allocate memory in heap, whose length is defined by strlen. The code is shown below.
int strLength = strlen(strInStack);
if (strLength == 0) {
printf("\"strInStack\" is empty.\n");
}
else {
char *strInHeap = (char *)malloc((strLength+1) * sizeof(char));
strcpy(strInHeap, strInStack);
}
return strInHeap;
Finally, copy the value of strInStack to strInHeap using strcpy, and return the pointer to strInHeap. The strInStack will be freed automatically because it only exits in this sub-function.
This is a function snippet I wrote to scan the user input for a string and then store that string on an array of the same size as the user input. Note that I initialize j to the value of 2 to be able to store the '\0' character.
char* dynamicstring() {
char *str = NULL;
int i = 0, j = 2, c;
str = (char*)malloc(sizeof(char));
//error checking
if (str == NULL) {
printf("Error allocating memory\n");
exit(EXIT_FAILURE);
}
while((c = getc(stdin)) && c != '\n')
{
str[i] = c;
str = realloc(str,j*sizeof(char));
//error checking
if (str == NULL) {
printf("Error allocating memory\n");
free(str);
exit(EXIT_FAILURE);
}
i++;
j++;
}
str[i] = '\0';
return str;
}
In main(), you can declare another char* variable to store the return value of dynamicstring() and then free that char* variable when you're done using it.
Here's a snippet which I wrote which performs the same functionality.
This code is similar to the one written by Kunal Wadhwa.
char *dynamicCharString()
{
char *str, c;
int i = 0;
str = (char*)malloc(1*sizeof(char));
while(c = getc(stdin),c!='\n')
{
str[i] = c;
i++;
realloc(str,i*sizeof(char));
}
str[i] = '\0';
return str;
}
char* load_string()
{
char* string = (char*) malloc(sizeof(char));
*string = '\0';
int key;
int sizer = 2;
char sup[2] = {'\0'};
while( (key = getc(stdin)) != '\n')
{
string = realloc(string,sizer * sizeof(char));
sup[0] = (char) key;
strcat(string,sup);
sizer++
}
return string;
}
int main()
{
char* str;
str = load_string();
return 0;
}
realloc is a pretty expensive action...
here's my way of receiving a string, the realloc ratio is not 1:1 :
char* getAString()
{
//define two indexes, one for logical size, other for physical
int logSize = 0, phySize = 1;
char *res, c;
res = (char *)malloc(sizeof(char));
//get a char from user, first time outside the loop
c = getchar();
//define the condition to stop receiving data
while(c != '\n')
{
if(logSize == phySize)
{
phySize *= 2;
res = (char *)realloc(res, sizeof(char) * phySize);
}
res[logSize++] = c;
c = getchar();
}
//here we diminish string to actual logical size, plus one for \0
res = (char *)realloc(res, sizeof(char *) * (logSize + 1));
res[logSize] = '\0';
return res;
}
Im trying to remove the first char of the string and keep the remainder, my current code doesnt compile and im confused on how to fix it.
My code:
char * newStr (char * charBuffer)
{
int len = strlen(charBuffer);
int i = 1;
char v;
if(charBuffer[0] == 'A' || charBuffer[0] == 'Q'){
for(i=1;i<len;i++)
v = v + charBuffer[i];
}
v = v + '\0';
return v;
}
Gcc: "Warning: return makes pointer from integer without a cast"
Also: "char * newStr (char * charBuffer)" needs to remain the same.
Strings don't work like this in C. You're summing up all of the characters in the buffer into the v variable. You can't use + to concatenate. The code you posted has some serious problems which indicate that there's an understanding gap with how to use C.
Try this:
char *newStr (char *charBuffer) {
int length = strlen(charBuffer);
char *str;
if (length <= 1) {
str = (char *) malloc(1);
str[0] = '\0';
} else {
str = (char *) malloc(length);
strcpy(str, &charBuffer[1]);
}
return str;
}
or this:
char *newStr (char *charBuffer) {
char *str;
if (strlen(charBuffer) == 0)
str = charBuffer;
else
str = charBuffer + 1;
return str;
}
Depending on whether you want to allocate a new string or not. You'll also have to add the code for handling the cases that don't start with 'Q' or 'A'. I didn't include those because I'm not sure exactly what you're trying to do here.
Make sure you do some research into allocating and deallocating memory with malloc and free. These are fundamental functions to be able to use if you're going to be doing C programming.
Well, your description says you want to deal with "strings", but you code deals with char buffers/pointers. The simplest approach to remove the first character for strings would be
const char *newStr(const char *string)
{
return string+1;
}
but as that doesn't look at all like what your code is doing, you probabaly want something different. For example, if you want to just remove a leading 'A' or 'Q' and then copy the string to a buffer, you want something like
char *newStr(const char *string)
{
if (string[0] == 'A' || string[0] == 'Q')
string++;
return strdup(string);
}
You can simply move your char pointer one character in:
char* newstring = oldstring + 1;
Your function is declared to return a char * and you are returning a char.
Furthermore, why don't you just return a pointer to the second character?
char * newStr (char * charBuffer)
{
if (charBuffer && (*charBuffer == 'A' || *charBuffer == 'Q')) return charBuffer + 1;
return charBuffer;
}
Several of the other answers recommended returning charBuffer + 1. As I noted in my previous comment:
This is bad practice. What if the string is dynamically allocated? Perhaps eventually the storage will be freed (starting from the second character). The string should be copied to new storage first.
Freeing a piece of storage from the middle will result in undefined behavior.
Instead, try the strdup function which will return a duplicate of the given string.
#include <string.h>
#include <stdio.h>
char *newStr(char* charBuffer) {
if (charBuffer && (charBuffer[0] == 'A' || charBuffer[0] == 'Q'))
return strdup(charBuffer + 1);
else
return strdup(charBuffer);
}
void main() {
char a[7] = "Advait";
char b[5] = "John";
printf("%s\n",newStr(a)); // Prints "dvait"
printf("%s\n",newStr(b)); // Prints "John"
}