"Error reading characters of string" C, Visual Studio 2013 - c

Ive been asked to write a function that merges two sorted (ascii sorted) strings without duplicates.
For example, for string1 = aabcd, and string2 = abbcdg, the end result string should be abcdg.
For some reason, the end result string doesnt allocate well, or so I think.. its not working anyway and its giving me weird characters instead of what its supposed to give.
The value of stringToReturn is always 0xfffffffe "Error reading characters of string", and inside it says "Unable to read memory"
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "bohan.h"
int main() {
char* string1;
char* string2;
char* mergedString;
string1 = (char*)malloc(MAX_TEXT + 1);
if (string1 == NULL)
return;
string2 = (char*)malloc(MAX_TEXT + 1);
if (string2 == NULL)
return;
printf("Please enter string no. 1: ");
scanf("%s", string1);
printf("Please enter string no. 2: ");
scanf("%s", string2);
mergedString = merge_strings(string1, string2);
printf("%s \n", mergedString);
free(string1);
free(string2);
free(mergedString);
}
bohan.c:
#include <stdio.h>
#include <stdlib.h>
#include "bohan.h"
int checkNumberOfChars(char* text) {
int sum = 0;
if (text == NULL)
return 0;
while (*text != '\0')
{
sum++;
text++;
}
return sum;
}
char* merge_strings(char* text1, char* text2) {
int i;
int hasChanged;
char* stringToReturn;
if (text1 == NULL && text2 == NULL)
return NULL;
stringToReturn = (char *)malloc(checkNumberOfChars(text1) + checkNumberOfChars(text2) + 1);
if (stringToReturn == NULL)
return NULL;
for (i = 1; i <= MAX_ASCII; i++) {
hasChanged = FALSE;
if (*text1 != '\0' || *text2 != '\0') {
if (*text1 != '\0') {
if (i == *text1) {
*stringToReturn = i;
stringToReturn++;
hasChanged = TRUE;
while (*text1 == i)
text1++;
}
}
if (*text2 != '\0') {
if (i == *text2) {
if (!hasChanged) {
*stringToReturn = i;
stringToReturn++;
}
while (*text2 == i)
text2++;
}
}
}
else
break;
}
return stringToReturn;
}
bohan.h:
#ifndef DEF
#define TRUE 1
#define FALSE 0
#define MAX_TEXT 100
#define MAX_ASCII 255
int checkNumberOfChars(char *text);
char *merge_strings(char *text1, char *text2);
#endif DEF

In the merge_strings method you must define a pointer (beginOfStringToReturn) to hold the address of the beginning of the merged string. The merge_strings method should return this pointer at the end. Also add '\0' after the merged string has been built.
char* merge_strings(char* text1, char* text2) {
int i;
int hasChanged;
char* stringToReturn;
if (text1 == NULL && text2 == NULL)
return NULL;
stringToReturn = (char *)malloc(checkNumberOfChars(text1) + checkNumberOfChars(text2) + 1);
char* beginOfStringToReturn = stringToReturn;
if (stringToReturn == NULL)
return NULL;
for (i = 1; i <= MAX_ASCII; i++) {
hasChanged = FALSE;
if (*text1 != '\0' || *text2 != '\0') {
if (*text1 != '\0') {
if (i == *text1) {
*stringToReturn = i;
stringToReturn++;
hasChanged = TRUE;
while (*text1 == i)
text1++;
}
}
if (*text2 != '\0') {
if (i == *text2) {
if (!hasChanged) {
*stringToReturn = i;
stringToReturn++;
}
while (*text2 == i)
text2++;
}
}
}
else
break;
}
*stringToReturn = '\0';
return beginOfStringToReturn;
}
In bohan.h include the guard like this:
#ifndef BOHAN_H
#define BOHAN_H
#define TRUE 1
#define FALSE 0
#define MAX_TEXT 100
#define MAX_ASCII 255
int checkNumberOfChars(char *text);
char *merge_strings(char *text1, char *text2);
#endif

Related

Reading in strings without header <string.h>

I am a newbie in C and for an exercise I have to write a program, where I can read in strings. If my reserved memory (length BUFFER_SIZE) isn't enough, it should reserve memory in increments of +=BUFFER_SIZE, as long as needed to read the string. I tried to write some functions to get this done, but it doesn't work. Can somebody please help me?
My code:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 10
size_t string_length(char *string)
{
size_t i = 0;
while(string[i] != '\0')
{
i++;
}
return i;
}
void string_concatenate(char *string, char *string_to_chain)
{
size_t length = string_length(string);
for(size_t i = 0; *(string_to_chain + i) != '\0'; i++, length++)
{
string[length] = string_to_chain [i];
}
string[length] = '\0';
}
char *string_search(char *string, char character)
{
do
{
if (*string == character)
{
return (char*)string;
}
} while (*string++);
return NULL;
}
char *get_line()
{
int line_size = BUFFER_SIZE;
char* line = malloc(line_size * sizeof(char));
if(line == NULL)
{
return NULL;
}
printf("Bitte Text eingeben: \n");
fgets(line, BUFFER_SIZE, stdin);
char *new_line_character = string_search(line, '\n');
while(new_line_character == NULL)
{
line_size += BUFFER_SIZE;
line = realloc(line, (line_size * sizeof(char)));
if(line == NULL)
{
return NULL;
}
char *new_line = line + BUFFER_SIZE - 1;
fgets(new_line, line_size, stdin);
new_line_character = string_search(line, '\n');
}
*new_line_character = '\0';
return line;
}
}
int main(void) {
char *string = get_line();
printf("s%\n", string);
}

Memory leak caused by realloc in valgrind C

I have a my_string object made that contains a char pointer, a size, and a capacity. I am trying to read words from a dictionary text file into the my_string object and print them to the screen. The default capacity is 7, so when I read a word that is longer than 7 characters, I need to reallocate some space at the end of the string. I haven't been able to implement this functionality correctly yet. It seems to work correctly, but when I run it in valgrind, there is apparently a memory leak somewhere in my code. Not sure where this is coming from, because I free the entire string after the program runs. If someone could help me with this you'd be a lifesaver. Here is my driver code, and my my_string.c file:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "my_string.h"
int main(int argc, char* argv[]) {
MY_STRING hMy_String = NULL;
FILE* fp;
hMy_String = my_string_init_default();
fp = fopen("dictionary.txt", "r");
int len;
while(my_string_extraction(hMy_String, fp)) {
len = my_string_get_size(hMy_String);
if(len == 8){
my_string_insertion(hMy_String, stdout);
printf("\n");
if(fgetc(fp) == ' '){
printf("Found a space after the string\n");
}
}
}
my_string_destroy(&hMy_String);
fclose(fp);
return 0;
}
my_string.c
#include <stdio.h>
#include <stdlib.h>
#include "my_string.h"
struct my_string {
int size;
int capacity;
char* data;
};
typedef struct my_string My_String;
MY_STRING my_string_init_default(void){
//default capacity of string is 7
//initializes pointer to My_String, set to NULL for good practice
My_String* pMy_String = NULL;
//allocates memory for default string
pMy_String = (My_String*)malloc(sizeof(My_String));
if(pMy_String != NULL) {
pMy_String->size = 0;
pMy_String->capacity = 7;
pMy_String->data = (char*)malloc(sizeof(char) * pMy_String->capacity);
if(pMy_String->data == NULL) {
free(pMy_String);
pMy_String = NULL;
}
}
//returns copy of address to default string
return pMy_String;
}
MY_STRING my_string_init_c_string(char* c_string) {
int i = 0;
//initializes a pointer to a My_String
My_String* theString = NULL;
//loops through string, for every character, i increases 1
while((*c_string) != '\0'){
c_string++;
i++;
}
//resets c_strings value from before the loop
c_string = c_string - i;
i++; //i needs to be 1 greater than the length of the string
//allocation
theString = malloc(sizeof(My_String) + i);
//if there was an error, return NULL
if(theString == NULL)
return NULL;
else {
//sets the values of the object to the given values
(*theString).size = (i - 1);
(*theString).capacity = i;
(*theString).data = c_string;
}
//returns address of the initialized string
return theString;
}
int my_string_get_capacity(MY_STRING hMy_string){
return sizeof(hMy_string);
}
int my_string_get_size(MY_STRING hMy_string) {
char* str = (char*) hMy_string;
int size = 0;
while(str[size] != '\0')
size++;
return size;
}
int my_string_compare(MY_STRING hLeft_string, MY_STRING hRight_string) {
// sets the strings to pointers to the My_String data type
My_String* Left = hLeft_string;
My_String* Right = hRight_string;
//variables for lexicographical value of each string
int left_lex = 0;
int right_lex = 0;
//loops through left string, adds up left_lex value
while((*Left->data) != '\0') {
left_lex += (*Left->data);
(*Left).data++;
}
//loops through right string, adds up right_lex value
while((*Right->data) != '\0') {
right_lex += (*Right->data);
(*Right).data++;
}
//does the comparison and returns the corrosponding value
if(left_lex < right_lex){
return -1;
}else if (left_lex == right_lex) {
return 0;
}else {
return 1;
}
}
Status my_string_extraction(MY_STRING hMy_string, FILE* fp) {
My_String* pMy_string = hMy_string;
int start = 0, end = 0;
char ch;
int strLength, capacity, i;
while(!feof(fp)){
ch = fgetc(fp);
if(ch == ' ' || ch == '\t' || ch == '\n' ||ch == '\r') {
continue;
}
else {
start = ftell(fp) - 1;
end = start + 1;
break;
}
}
if(end == 0){
return FAILURE;
}
while(!feof(fp)) {
ch = fgetc(fp);
end++;
if(ch == ' ' || ch == '\t' || ch == '\n' ||ch == '\r'){
break;
}
}
strLength = end - start - 1;
(*pMy_string).size = strLength;
if(strLength == 0){
return FAILURE;
}
capacity = my_string_get_capacity(hMy_string);
if(strLength >= capacity){
hMy_string = realloc(hMy_string, strLength + 1);
}
fseek(fp, start, SEEK_SET);
char* str = (char*)hMy_string;
for(i = 0; i < strLength; i++) {
str[i] = fgetc(fp);
}
str[i] = '\0';
return SUCCESS;
}
Status my_string_insertion(MY_STRING hMy_string, FILE* fp) {
char* str = (char*)hMy_string;
if(fprintf(fp, "%s", str))
return SUCCESS;
else
return FAILURE;
}
void my_string_destroy(MY_STRING* phMy_string){
free(*phMy_string);
*phMy_string = NULL;
}

How to print only the first sentence in string [C]?

Example:
void stringEvaluation(char *name){
if (strstr(name, "Tall") != NULL)
--here I would like to print only "John Doe"--
}
int main{
char name[160 + 1];
scanf("%[^\n]%*c", name);
stringEvaluation(name);
return 0;
}
and this is the input
"John Doe (45). Black. Tall. Brown eyes"
Your request is unclear. For example, do as follows.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void stringEvaluation(const char *s){
const char *p;
if(s == NULL || *s == '\0'){
puts("invalid format.");
return ;
}
(p = strchr(s, '(')) || (p = strchr(s, '.'));
if(p == NULL){
puts("invalid format.");
return ;
}
//find end
while(!isalpha((unsigned char)p[-1]))
--p;
while(s < p)
putchar(*s++);
}
int main(void){
char name[160 + 1] = "";
scanf("%160[^\n]%*c", name);
stringEvaluation(name);
return 0;
}
I am using strtok() to get the name. Please note, this will work only if you have "()" in your string.
void stringEvaluation(char *name){
if (strstr(name, "Tall") != NULL)
{
char *nameEnd = strtok(name, "("); //Returns address of '('
if(NULL != nameEnd)
{
int nameLength = nameEnd - name - 1; // 1 for space after name.
char *onlyName = malloc((nameLength + 1) * sizeof(char)); // 1 for terminating '\0'
if(NULL != onlyName)
{
//Copy name part.
strncpy(onlyName, name, nameLength);
onlyName[nameLength] = '\0'; //Make onlyName a string
printf("Name: [%s]\n", onlyName);
free(onlyName);
onlyName = NULL;
}
}
}
}
I have assumed that name will be at first place in your input string. Then following small logic will work for you.
void stringEvaluation(char *name){
char *p;
char OutPut[50]={0};
if (strstr(name, "Tall") != NULL)
{
p = strstr(name," ");
p++;
p = strstr(p," ");
strncpy(OutPut,name,(p-name));
printf("name=%s\n",OutPut);
}
}

C - Find a word and get the next two

I am parsing a file in C, line by line. Here is an exemple of what I am trying to do :
I have a line for example :
word word word WORDTOFIND: word1 word2 word word
What I want to do is : When I find the word WORDTOFIND, get the two next words (word1 and word2 in this case) of the line. Is there an easy way to do that in C ? I know about the strstr function, but I don't find a way to get the next two words word1 and word2 after I found the good one.
One approach would be this:
int main(void)
{
char *str = "rated rat cat bat hat";
char *key = "rat ";
char *pointer = NULL;
char nwords = 2;
if ((pointer = strstr(str, key)) != NULL)
{
while (*pointer != ' ') pointer++;
while (nwords >= 0)
{
printf("%c", *pointer);
if (*pointer == ' ') {
nwords--;
} else if (*pointer == '\0') {
exit(0);
}
pointer++;
}
}
}
You can try an aproach like this, using strtok to parse the words at every space. This code also uses malloc and realloc to allocate space for an array of strings, and grows it when needed.
The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
void exit_if_null(void *ptr, const char *msg);
char *stripped_word(char *word);
int
main(int argc, char const *argv[]) {
FILE *filename;
char line[MAXCHAR];
char *word, *newword;
char **allwords;
int init_size = 8, count = 0, i;
const char *key = "WORDTOFIND";
filename = fopen("files.txt", "r");
if (filename == NULL) {
fprintf(stderr, "%s\n", "Error reading file!");
exit(EXIT_FAILURE);
}
allwords = malloc(init_size * sizeof(*allwords));
exit_if_null(allwords, "Initial Allocation");
while (fgets(line, MAXCHAR, filename) != NULL) {
word = strtok(line, " \n");
while (word != NULL) {
if (count == init_size) {
init_size *= 2;
allwords = realloc(allwords, init_size * sizeof(*allwords));
}
allwords[count] = malloc(strlen(word)+1);
exit_if_null(allwords[count], "Initial Allocation");
newword = stripped_word(word);
strcpy(allwords[count], newword);
count++;
word = strtok(NULL, " \n");
free(newword);
}
}
for (i = 0; i < count; i++) {
if (strcmp(key, allwords[i]) == 0) {
printf("Next two words:\n");
printf("%s\n", allwords[i+1]);
printf("%s\n", allwords[i+2]);
}
free(allwords[i]);
allwords[i] = NULL;
}
free(allwords);
allwords = NULL;
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
char
*stripped_word(char *word) {
int i, pos = 0;
char *result;
result = malloc(strlen(word)+1);
exit_if_null(result, "Initial Allocation");
for (i = 0; word[i] != '\0'; i++) {
if (isalpha(word[i]) || isdigit(word[i])) {
result[pos++] = word[i];
}
}
result[pos] = '\0';
return result;
}

String Search and format in C

Just a quick one: in C I have a buffer full of data like below:
char buffer[255]="CODE=12345-MODE-12453-CODE1-12355"
My question is how to search through this. For example for the CODE=12345, section bear in mind that the numbers change, so I would like to search like this CODE=***** using wildcard or preset amount of spaces after the CODE= part.
This method wont compile last one left to try
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main ()
{
char buf[255]="CODE=12345-MODE-12453-CODE1-12355";
#define TRIMSPACES(p) while(*p != '\0' && isspace((unsigned char)*p) != 0) ++p
#define NSTRIP(p, n) p += n
#define STRIP(p) ++p
char* getcode(const char *input)
{
char *p = (char*) input, *buf, *pbuf;
if((buf = malloc(256)) == NULL)
return NULL;
pbuf = buf;
while(*p != '\0') {
if(strncmp(p, "CODE", 3) == 0) {
NSTRIP(p, 4); //remove 'code'
TRIMSPACES(p);//trim white-space after 'code'
if(*p != '=')
return NULL;
STRIP(p); // remove '='
TRIMSPACES(p); //trim white-spaces after '='
/* copy the value until found a '-'
note: you must be control the size of it,
for avoid overflow. we allocated size, that's 256
or do subsequent calls to realloc()
*/
while(*p != '\0' && *p != '-')
*pbuf ++ = *p++;
// break;
}
p ++;
}
//put 0-terminator.
*pbuf ++ = '\0';
return buf;
}
//
}
You could use the sscanf() function:
int number;
sscanf(buffer, "CODE = %i", &number);
for that to work well your buffer has to be null terminated.
Another way to do it instead of sscanf():
char *input, *code;
input = strstr(buf, "CODE");
if(input == NULL) {
printf("Not found CODE=\n");
return -1;
}
code = strtok(strdup(input), "=");
if(code != NULL) {
code = strtok(NULL, "-");
printf("%s\n", code); // code = atoi(code);
} else {
//not found '='
}
Or more robust way.. a bit more complex:
#define TRIMSPACES(p) while(*p != '\0' && isspace((unsigned char)*p) != 0) ++p
#define NSTRIP(p, n) p += n
#define STRIP(p) ++p
char* getcode(const char *input, size_t limit)
{
char *p = (char*) input, *buf, *pbuf;
size_t i = 0;
while(*p != '\0') {
if(strncmp(p, "CODE", 3) == 0) {
NSTRIP(p, 4); //remove 'code'
TRIMSPACES(p);//trim all white-spaces after 'code'
/* check we have a '=' after CODE (without spaces).
if there is not, returns NULL
*/
if(*p != '=')
return NULL;
/* ok. We have.. now we don't need of it
just remove it from we output string.
*/
STRIP(p);
/* remove again all white-spaces after '=' */
TRIMSPACES(p);
/* the rest of string is not valid,
because are white-spaces values.
*/
if(*p == '\0')
return NULL;
/* allocate space for store the value
between code= and -.
this limit is set into second parameter.
*/
if((buf = malloc(limit)) == NULL)
return NULL;
/* copy the value until found a '-'
note: you must be control the size of it,
for don't overflow. we allocated 256 bytes.
if the string is greater it, do implementation with
subjecents call to realloc()
*/
pbuf = buf;
while(*p != '\0' && *p != '-' && i < limit) {
*pbuf ++ = *p++;
i ++;
}
*pbuf ++ = '\0';
return buf;
}
p ++;
}
return NULL;
}
And then:
char buf[255] = "foo baa CODE = 12345-MODE-12453-CODE-12355";
char *code = getcode(buf,256);
if(code != NULL) {
printf("code = %s\n", code);
free(code);
} else {
printf("Not found code.\n");
}
output:
code = 12345
Check out this online.
if you want to don't differentiate case, you can use the strncasecmp() that's POSIX function.
Assuming the CODE= part always comes at the beginning of the string, it's pretty easy:
sscanf(buffer, "CODE = %d", &number);
...but you want buffer to be char[255], not unsigned long.
Edit: If the CODE= part isn't necessarily at the beginning of the string, you can use strstr to find CODE in the buffer, do your sscanf starting from that point, then look immediately following that:
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
Edit2:
For example, you'd use this something like this:
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main ()
{
// This is full of other junk as well
char buffer[255]="CODE=12345 MODE-12453 CODE=12355" ;
int i;
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
for (i=0; i<current; i++)
printf("%d\n", codes[i]);
return 0;
}
For me, this produces the following output:
12345
12355
...correctly reading the two "CODE=xxx" sections, but skipings over the "MODE=yyy" section.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getcode(const char *str, const char *pattern){
//pattern: char is match, space is skip, * is collect
static const char *p=NULL;
char *retbuf, *pat;
int i, match, skip, patlen;
if(str != NULL) p=str;
if(p==NULL || *p=='\0') return NULL;
if(NULL==(retbuf=(char*)malloc((strlen(p)+1)*sizeof(char))))
return NULL;
pat = (char*)pattern;
patlen = strlen(pat);
i = match = skip = 0;
while(*p){
if(isspace(*p)){
++p;
++skip;
continue;
}
if(*pat){
if(*p == *pat){
++match;
++p;
++pat;
} else if(*pat == '*'){
++match;
retbuf[i++]=*p++;
++pat;
} else {
if(match){//reset
pat=(char*)pattern;
p -= match + skip -1;
i = match = skip = 0;
} else //next
++p;
}
} else {
break;
}
}
if(i){//has match
retbuf[i++]='\0';
retbuf=realloc(retbuf, i);
return retbuf;
} else {
free(retbuf);
return NULL;
}
}
int main (){
char *code;
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(" CODE = 12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode("CODE-12345-MODE-12453-CODE1-12355", "CODE=*****");
if(code==NULL)printf("not match\n");//not match
code=getcode("CODE=12345-MODE-12453-CODE=12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE=*****");
printf("\"%s\"\n",code);//"12355"
free(code);
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE1-*****");
printf("\"%s\"\n",code);//"12355"
free(code);
return 0;
}

Resources