I have a bigger string and I want to add the \0 character before a specific string is contained.
ex:
inputString = "some2.text.here"; => outputText = "some2";
I manage to find the last position of the output text, I don't know how to add \0 and make the pointer end here.
void test()
{
char* str = "some2.text.here";
char* search = ".text.here";
char * new;
//size text to be removed
int lengthOfStr = 10; //search length
int size = 0;
char stringEnding = '\0';
char * newPath;
new = '\0';
for(int i = 0; i < 200; i++){
if(*(str + i) == '\0'){
printf("found on index %d", i);
printf("\n i: %d \n lengthOfStr : %d", i, lengthOfStr);
new = (char *) malloc(i - lengthOfStr);
memcpy(new, str, sizeof(i - lengthOfStr));
break;
}
}
printf("\n string value : %s", new);
}
Here I try to copy a specific length but is not working well... I also tried to add str[5] = '\0'but also did not did the trick... Any tips?
There seems to be 3 problems.
Too little memory allocated
Wrong number of bytes copied
Missing string termination
Something like:
new = malloc(i - lengthOfStr + 1); // Allocate 1 more char
memcpy(new, str, i - lengthOfStr); // Correct number of bytes to copy
new[i - lengthOfStr] = '\0'; // Terminate the string
BTW: Your current code always expects the "search" string to be in the end of the current string. Maybe that's what you want but it seems to me that you should use strstr instead of a loop. And... use strlen instead of a hard code length.
Related
My function is not returning a string as expected, however, it does return before the for loop, and even returns a string if I place the return statement within the loop, but seems to ignore afterward.I'm at a complete loss as to why it doesn't return anything after the loop. Here's my code:
char * encode(char *plaintext, char *key){
char *message, *keyStr, *crypt;
char str[0], letter;
int keysize, i, num, n, plainInput[sizeof(plaintext)],
keyInt[sizeof(plaintext)], keyAndMessage[sizeof(plaintext)];
unsigned size;
size = (unsigned)strlen(plaintext);
keysize = (unsigned)strlen(key);
if(size != keysize){
printf("the key size is: %d\n", keysize);
printf("the plain text size is %d\n", size);
return "Key and Plaintext Size Mismatch.";
}
message = malloc(size);
keyStr = malloc(size);
crypt = malloc(size);
for(i = 0; i < size; i++){
// convert plaintext to ints
letter = plaintext[i]; // could be any upper or lower case
str[0] = letter; // place char into new memory location
num = strtol( str, NULL, 36 ) - 10; // convert the letter to a number
plainInput[i] = num; // store each number in an array ->
numInput
// convert keys to ints
letter = key[i]; // could be any upper or lower case
str[0] = letter; // place char into new memory location
num = strtol( str, NULL, 36 ) - 10; // convert the letter to a number
keyInt[i] = num; // store each number in an array ->
keyAndMessage[i] = (keyInt[i] + plainInput[i]) % 27;
// convert key to ascii for debugging only
keyStr[i] = (char)keyInt[i]+65;
// convert message to ascii text
message[i] = (char)plainInput[i]+65;
// combine message and key
plaintext[i] = (char)keyAndMessage[i]+65;
}
printf("the original message is: %s\n", message);
printf("the key is : %s\n", key);
printf("the crypt is : %s\n", plaintext);
printf("the size of origin is: %lu\n", sizeof(message));
printf("the size of key is: %lu\n", sizeof(key));
printf("the size of crypt is: %lu\n", sizeof(plaintext));
return plaintext;
#BLUEPIXY makes one good point... probably the best solution to that is to define size earlier, then use that for your array sizes (use size+1 to allow room for terminating null):
char * encode(char *plaintext, char *key){
char *message, *keyStr, *crypt;
size_t size = strlen(plaintext);
int plainInput[size+1], keyInt[size+1], keyAndMessage[size+1];
:
:
but you have another problem as well: you've defined str to be an array of length 0, when it should be length 2... one for the letter, one for the terminating null character.
char str[2];
Though your conversion would be simpler (and more efficient) if you just used the character encoding directly:
num = toupper(letter) - 'A'; // convert the letter to a number
Also, you've allowed no space in your mallocs for a terminating null, and you have not put in the terminating null, so you are printing unterminated strings... which produces undefined behavior. Change your mallocs as follows:
message = malloc(size+1);
keyStr = malloc(size+1);
crypt = malloc(size+1);
and be sure to terminate your strings before trying to print them:
message[size] = 0;
keyStr[size] = 0;
crypt[size] = 0;
Oh, and as pointed out earlier, sizeof will only give you the size of the pointers (in the printfs at the end), not the size of the string. You need strlen there again.
And one more thing... your function tries to modify the string passed in (plaintext), which is a bad idea because it could be a constant string. Better to put the new characters into a malloced buffer, as with message, et.al. Also, you neglected to free your malloced buffers...memory leak!
Hopefully this will get you closer!
I'm trying to solve a code to strip a sentence down only to it's alpha character, using the following code, but the code always gives me a runtime error(The commented parts are steps I had taken to figure out the solution).
[Ex: Test'sen- tence should print Testsentence]
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFFER_LEN 1000
#define BUFFER_INCR 15
int main(void)
{
int buffer_length = BUFFER_LEN;
char *pString = malloc(BUFFER_LEN);/* initial array */
char *pTemp_start = pString;
long long int String_len = 0;
char *pTemp = NULL;
int copy = 0;
int count = 0;/*delete this after check*/
while((*pString++ = getchar()) != '\n')
{
String_len = pString - pTemp_start;
printf("\nThe character you inputted is: %c", *(pString+count++));
//getchar();
if(String_len == (buffer_length - 1))/*reserve one for newline*/
{
buffer_length += BUFFER_INCR;
pTemp = realloc(pString, buffer_length);/*reallocate space for
15 more chars.*/
pTemp_start = pTemp - String_len;
pString = pTemp;
free(pTemp);
pTemp = NULL;
if(!pString)
{
printf("The space couldn't be allocated");
return 1;
}
}
}
/*checks that can be done for addresses*/
//printf("\nThe length of the string is: %lld", pString - pTemp_start);
*(--pString) = '\0';
//printf("\nThe charcter at the end is: %d", *(pString + String_len - 1));
//printf("\nThe character at the mid is: %d", *(pString + 2));
printf("The input string is: %c", *pString);
/*code to remove spaces*/
for(int i = 0; i < (String_len + 1); i++)
{
if((isalnum(pString[i])))
{
*(pString + copy++) = *(pString +i);
}
}
*(pString + copy) = '\0';/*append the string's lost null character*/
printf("\nThe stripped string is: \n%s", pString);
return 0;
}
The code simply doesn't print anything that's inputted.
So you've got a conflict in your code between this line
while((*pString++ = getchar()) != '\n')
and lines like the following.
pTemp = realloc(pString, buffer_length);
The first line I've quoted is incrementing the position of pString within your allocated memory, but the second one is acting as if pString is still pointing to the start of it. realloc() won't work unless pString is pointing to the start of the allocated memory. You're then not checking the results of the realloc() call, assigning the new memory block to pString and then freeing the newly allocated memory. So you're definitely going to have unexpected results.
You also have to remember that stdin is buffered, so your code will wait until it's got an entire line to read before doing anything. And stdout is also buffered, so only lines that end in a \n will be output. So you probably want to have the following...
printf("The character you inputted is: %c\n", *pString);
...or something similar bearing in mind the issues with how you're using pString.
realloc(pString,...) does not add an allocated block, it replaces the one being reallocated (in this case, pString). So pString isn't (necessarily) a valid pointer after that call. Worse, you then free(pTemp), so you no longer have anything allocated.
I am trying to find and replace all occurrences of a substring within an array of strings in C. I think I have most of the logic down, however I dont know where I am messing up for the remaining parts.
Here is the relevant code - the string I am replacing is in searchStr and I am trying to replace it with replaceStr. The array of strings is called buff. I do not need to save the modified string back into the array after, I just need to print the modified string to the console.
for (size_t i = 0; i < numLines; i++) {
char *tmp = buff[i];
char finalStr[MAX_STR_LEN * 2];
char temporaryString[MAX_STR_LEN];
int match = 0;
while ((tmp = strstr(tmp, searchStr))) {
match = 1;
char temporaryString[MAX_STR_LEN];
char tmp2[MAX_STR_LEN];
printf("Buff[i]: %s", buff[i]);
sprintf(temporaryString, "%s", strstr(tmp, searchStr) + strlen(searchStr)); // Grab everything after the match
printf("Behind: %s", temporaryString);
strncpy(tmp2, buff[i], tmp - buff[i]); // Grab everything before the match
strcat(finalStr, tmp2);
printf("In Front: %s\n", finalStr);
strcat(finalStr, replaceStr); // Concat everything before with the replacing string
tmp = tmp + strlen(searchStr);
buff[i] = tmp; // Move buff pointer up so that it looks for another match in the remaining part of the string
}
if (match) {
strcat(finalStr, temporaryString); // Add on any remaining bytes
printf("Final: %s\n", finalStr);
}
}
If have a lot of printf in there just so I can see where everything is for debugging.
Example case:
If I am running it against the string what4is4this with searchStr = 4 and replaceStr = !!! this is the output in the console... I am adding annotations as well using //
Buff[i]: what4is4this // Just printing out the current string before we attempt to replace anything
Behind: is4this // Looking good here
In Front: hat // Why is it cutting off the 'w'?
Buff[i]: is4this // Good - this is the remaining string we need to look through
Behind: this // Again, looking good
In Front: hat!!!isat // It should be 'is'
Final: hat!!!isat!!!isat // final should be 'what!!!is!!!this'
Any ideas guys? Im tearing my hair out trying to fix this
Thanks!
It is an unhealthy mix of pointer-juggling and undefined behavior, but the commenters already told you that. If you simplify it a bit and make good and frugal use of pointers you can do something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ALL CHECKS OMMITTED!
#define MAX_STR_LEN 1024
int main(int argc, char **argv)
{
char *buff, *cpbuff;
char *searchStr;
char *replaceStr;
// pointers too the two parts with the search string in between
char *tmp, *after;
// the final output (a fixed length is not good,
// should be dynamically allocated)
char finalStr[MAX_STR_LEN * 2] = { '\0' };
if (argc < 4) {
fprintf(stderr, "Usage: %s string searchstr replacestr\n", argv[0]);
exit(EXIT_FAILURE);
}
buff = malloc(strlen(argv[1]) + 1);
strcpy(buff, argv[1]);
searchStr = malloc(strlen(argv[2]) + 1);
strcpy(searchStr, argv[2]);
replaceStr = malloc(strlen(argv[3]) + 1);
strcpy(replaceStr, argv[3]);
// Keep a finger on the start of buff
cpbuff = buff;
while (1) {
printf("Buff: %s\n", buff);
// Grab everything after the match
after = strstr(buff, searchStr);
// No further matches? Than we're done
if (after == NULL) {
strcat(finalStr, buff);
break;
}
// assuming strlen(searchStr) >= 1
tmp = buff;
// mark the end of the first part
tmp[after - buff] = '\0';
// set the after pointer to the start of the second part
after = after + strlen(searchStr);
printf("Behind: %s\n", after);
printf("Before: %s\n\n", tmp);
// Put the first part to it's final place
strcat(finalStr, tmp);
// concat the replacement string
strcat(finalStr, replaceStr);
// Set buff to the start of the second part
buff = after + strlen(searchStr) - 1;
}
printf("Final: %s\n", finalStr);
// set the buff pointer back to it's start
buff = cpbuff;
free(buff);
free(searchStr);
free(replaceStr);
exit(EXIT_SUCCESS);
}
The single point that can be called an abuse of pointer arithmetic is the line that marks the end of the first part. It can be avoided by measuring and using the lengths of the involved strings and do arithmetic with them. It is slower, admitted, so it depends on your individual use case.
It is still more complicated than I like it, but it's a start.
I hope you can extend it now to several lines of input by yourself.
I'm using C to read in an external text file. The input is not great and would look like;
0PAUL 22 ACACIA AVENUE 02/07/1986RN666
As you can see I have no obvious delimeter, and sometimes the values have no space between them. However I do know how long in character length each value should be when split. Which is as follows,
id = 1
name = 20
house number = 5
street name = 40
date of birth = 10
reference = 5
I've set up a structure I want to hold this information in, and have tried using fscanf to read in the file.
However I find something along the lines of just isn't doing what I need,
fscanf(file_in, "%1d, %20s", person.id[i], person.name[i]);
(The actual line I use attempts to grab all input but you should see where I'm going...)
The long term intention is to reformat the input file into another output file which would be made a little easier on the eye.
I appreciate I'm probably going about this all the wrong way, but I would hugely appreciate it if somebody could set me on the right path. If you're able to take it easy on me in regard to an obvious lack of understanding, I'd appreciate that also.
Thanks for reading
Use fgets to read each line at a time, then extract each field from the input line. Warning: no range checks is performed on buffers, so attention must be kept to resize buffers opportunely.
For example something like this (I don't compile it, so maybe some errors exist):
void copy_substr(const char * pBuffer, int content_size, int start_idx, int end_idx, char * pOutBuffer)
{
end_idx = end_idx > content_size ? content_size : end_idx;
int j = 0;
for (int i = start_idx; i < end_idx; i++)
pOutBuffer[j++] = pBuffer[i];
pOutBuffer[j] = 0;
return;
}
void test_solution()
{
char buffer_char[200];
fgets(buffer_char,sizeof(buffer_char),stdin); // use your own FILE handle instead of stdin
int len = strlen(buffer_char);
char temp_buffer[100];
// Reading first field: str[0..1), so only the char 0 (len=1)
int field_size = 1;
int filed_start_ofs = 0;
copy_substr(buffer_char, len, filed_start_ofs, filed_start_ofs + field_size, temp_buffer);
}
scanf is a good way to do it, you just need to use a buffer and call sscanf multiple times and give the good offsets.
For example :
char buffer[100];
fscanf(file_in, "%s",buffer);
sscanf(buffer, "%1d", person.id[i]);
sscanf(buffer+1, "%20s", person.name[i]);
sscanf(buffer+1+20, "%5d", person.street_number[i]);
and so on.
I feel like it is the easiest way to do it.
Please also consider using an array of your struct instead of a struct of arrays, it just feels wrong to have person.id[i] and not person[i].id
If you have fixed column widths, you can use pointer arithmetic to access substrings of your string str. if you have a starting index begin,
printf("%s", str + begin) ;
will print the substring beginning at begin and up to the end. If you want to print a string of a certain length, you can use printf's precision specifier .*, which takes a maximum length as additional argument:
printf("%.*s", length, str + begin) ;
If you want to copy the string to a temporary buffer, you could use strncpy, which will generate a null terminated string if the buffer is larger than the substring length. You could also use snprintf according to the above pattern:
char buf[length + 1];
snprintf(buf, sizeof(buf), "%.*s", length, str + begin) ;
This will extract leading and trailing spaces, which is probably not what you want. You could write a function to strip the unwanted whitespace; there should be plenty of examples here on SO.
You could also strip the whitespace when copying the substring. The example code below does this with the isspace function/macro from <ctype.h>:
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
int extract(char *buf, const char *str, int len)
{
const char *end = str + len;
int tail = -1;
int i = 0;
// skip leading white space;
while (str < end && *str && isspace(*str)) str++;
// copy string
while (str < end && *str) {
if (!isspace(*str)) tail = i + 1;
buf[i++] = *str++;
}
if (tail < 0) tail= i;
buf[tail] = '\0';
return tail;
}
int main()
{
char str[][80] = {
"0PAUL 22 ACACIA AVENUE 02/07/1986RN666",
"1BOB 1 POLK ST 01/04/1988RN802",
"2ALICE 99 WEST HIGHLAND CAUSEWAY 28/06/1982RN774"
};
int i;
for (i = 0; i < 3; i++) {
char *p = str[i];
char id[2];
char name[20];
char number[6];
char street[35];
char bday[11];
char ref[11];
extract(id, p + 0, 1);
extract(name, p + 1, 19);
extract(number, p + 20, 5);
extract(street, p + 25, 34);
extract(bday, p + 59, 10);
extract(ref, p + 69, 10);
printf("<person id='%s'>\n", id);
printf(" <name>%s</name>\n", name);
printf(" <house>%s</house>\n", number);
printf(" <street>%s</street>\n", street);
printf(" <birthday>%s</birthday>\n", bday);
printf(" <reference>%s</reference>\n", ref);
printf("</person>\n\n");
}
return 0;
}
There's a danger here, however: When you access a string at a certain position str + pos you should make sure that you don't go beyond the actual string length. For example, you string may be terminated after the name. When you access the birthday, you access valid memory, but it might contain garbage.
You can avoid this problem by padding the full string with spaces.
Create a function in C that takes a string as a parameter and copy it to a new string.
If the original string is "abc", then the new string should be "aabbcc", if the original string is "4", then the newstring should be 44 etc. I believe i understand the concepts needed to solve a problem like this, but i just can't get the new string to be printed in the console. Here is my function:
void eco(char * str)
{
int count = 0;
/*Counts the number of symbols in the string*/
while(*(str + count) != '\0')
{
count++;
}
/*Memory for the new string, wich should be 6 chars long ("aabbcc").*/
char * newstr = malloc(sizeof(char *) * (count * 2));
/*Creating the content for newstr.*/
while(count > 0)
{
*newstr = *str; //newstr[0] = 'a'
*newstr++; //next newstr pos
*newstr = *str; //newstr[1] = 'a'
*str++; //next strpos
count--;
}
/*I can't understand why this would not print aabbcc*/
printf("%s", newstr);
/*free newstr from memory*/
free(newstr);
}
I have tried to print every char individually inside the while loop that creates the content for newstr, and that work. But when i try with the "%s"-flag i either get strange non-keyboard symbols or nothing at all.
I can't understand why this would not print "aabbcc"
It wouldn't do it for two reasons:
You are not passing a pointer to the beginning of the string, and
Because you did not add a null terminator
To fix the first problem, store the pointer to the block allocated to newstr in a temporary before doing the increments.
To fix the second problem, add *newstr = '\0' after the loop, and adjust malloc call to add an extra char for the terminator.
// Do not multiply by sizeof(char), because the standard requires it to be 1
// You used sizeof(char*), which is wrong too.
char * newstr = malloc((count * 2) + 1);
char *res = newstr; // Store the original pointer
// Your implementation of the actual algorithm looks right
while (...) {
... // Do the loop
}
*newstr = '\0';
printf("%s\n", res); // Pass the original pointer
Your loop advances newstr, so after it completes, it's not pointing at the beginning of the string anymore. You need to save the original pointer to use for printing.
For a start this line
char * newstr = malloc(sizeof(char *) * (count * 2));
should be
char * newstr = malloc(1 + (count * 2));
to include the null character
Then you forgot to add it
Also newstr points to the end to the new string