Resetting a char buffer in C - c

I'm working on a homework assignment and I need to basically create a character buffer. One of the functions I need to create is called "b_reset". It's purpose is to reinitialize the given buffer so that it will point to the first position in the char buffer. This is needed because later on, when a new char is added to the buffer, it needs to be added to the first position in the buffer.
This is the code I have thus far:
The struct:
typedef struct BufferDescriptor {
char * ca_head ;
int capacity ;
char inc_factor;
int addc_offset ;
int mark_offset ;
char r_flag;
char mode;
} Buffer ;
The code:
int b_reset ( Buffer *pB )
{
Buffer *temp = NULL;
int i = 0;
int j = 1;
if (pB == NULL)
{
return R_FAIL_1;
}
else
{
temp = (Buffer*)malloc(sizeof(Buffer*));
if (temp == NULL)
{
return R_FAIL_1;
}
temp->ca_head = (char*)malloc(pB->capacity);
if (!temp->ca_head)
{
temp = NULL;
return R_FAIL_1;
}
for(i = 0;i < ca_getsize(pB);++i)
{
temp->ca_head[j] = pB->ca_head[i];
j++;
}
pB->ca_head = temp->ca_head;
//free(temp->ca_head);
//free(temp);
return 0;
}
}
My goal in this code was to create a temporary buffer that would basically shift over everything 1 time based on the actual given buffer. This would make the first position empty so another char could be added.
The problem I'm running into is that the original buffer doesn't seem to be returning the right values after I reset it.
When I do this for example:
temp->ca_head[0] = 'a';
temp->ca_head[1] = 'b';
temp->ca_head[2] = 'c';
temp->ca_head[3] = 'd';
temp->ca_head[4] = 'e';
b_reset(temp); //this will return the size as 0, when it's actually 5
//temp->ca_head[0] = 'i'; //if this is executed, it returns the size as 6
//and prints out the right values, but if it's not,
//it will not print out anything
printf("%d", ca_getsize(temp));
for(i = 0;i < ca_getsize(temp);++i)
{
printf("%c", temp->ca_head[i]);
}
I know something is going wrong here, but I'm not too sure what. Any suggestions would be greatly appreciated.

This code is based on your followup comment:
well I'm not trying to resize the buffer, I just want to create an
empty space in the first position, so basically shifting everything to
the right 1 time. The assumption is that there is a enough space in
the buffer to handle this process.
I don't think you need to do any malloc() ing beyond the initial one. You can just shift everything up in a loop:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define R_FAIL_1 1
#define BUFFER_SIZE 10
typedef struct BufferDescriptor {
char * ca_head ;
int capacity ;
char inc_factor;
int addc_offset ;
int mark_offset ;
char r_flag;
char mode;
} Buffer ;
void allocate_buffer(Buffer *pB, int size)
{
pB->ca_head = malloc(size);
assert(pB->ca_head);
pB->capacity = size;
}
int ca_getsize( Buffer *pB)
{
return pB->capacity;
}
int b_reset ( Buffer *pB )
{
int i = 0;
if (pB == NULL)
{
return R_FAIL_1;
}
else
{
if ( ca_getsize(pB) <= 0 || pB->ca_head == NULL )
return R_FAIL_1;
}
// shift data up by 1 byte
for( i = ca_getsize(pB) - 1 ; i > 0;i-- )
{
pB->ca_head[i] = pB->ca_head[i-1];
}
pB->ca_head[0] = '\0';
return 0;
}
void print_buffer(Buffer *pB)
{
printf("capacity: %d \n", ca_getsize(pB));
for (int i = 0;i < ca_getsize(pB);++i)
{
printf("buffer(%d): [%d] ",i, pB->ca_head[i]);
}
printf("\n");
}
int main(void)
{
Buffer a_buffer;
allocate_buffer(&a_buffer,BUFFER_SIZE);
strcpy(a_buffer.ca_head,"abcdefgh");
print_buffer(&a_buffer);
int ret = b_reset(&a_buffer);
assert(ret == 0);
print_buffer(&a_buffer);
}

temp = (Buffer*)malloc(sizeof(Buffer*));
You need to allocate enough space to hold a Buffer, but you only allocate enough space to hold a pointer to a buffer. This should be:
temp = (Buffer*)malloc(sizeof(Buffer));

You are managing your memory incorrectly. You are allocating memory for a new Buffer struct when actually you only need to handle the memory of the ca_head member (if my interpretation of your homework problem is correct).
Each time you invoke b_reset, you will allocate memory for this struct that will not be released. If you don't handle your memory correctly, you will experience unexpected results as the one you are reporting in your question.
I suggest you to make a research on the function realloc and use it properly in your b_reset function.
Good luck with your homework.

Related

Issue with hashtable in c

So I have an assignment to create a program in c that reads a couple of sentences(a 140mb file), and based on the 2nd input, which is a number, I need to return the Nth most common word. My idea was to build a hash table with linear probing, every time I get a new element I hash it accordingly based its position and based on djb2, else if there is a collision I rehash. After that, I apply Quicksort based on the occurrence and then I finally access by index.
I am having issues finishing up a hash table with linear probing in c. I am pretty sure I have finished it but every time I run I am getting a heap buffer overflow on lldb. I tried to spot the issue but I still cannot figure it out.
Am I getting out of memory on stack? The file is relatively small to consume so much memory.
I used address sanitiser and I got a heap-buffer-overflow on inserting.
I don't think I am touching the memory outside the allocate region but I am not 100% sure.
Any idea what has gone wrong? This is the table.c implementation and below that you can see the form of the struct.
Here is a more detailed message from address sanitiser:
thread #1: tid = 0x148b44, 0x0000000100166b20 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie(), queue = 'com.apple.main-thread', stop reason = Heap buffer overflow
{
"access_size": 1,
"access_type": 1,
"address": 105690555220216,
"description": "heap-buffer-overflow",
"instrumentation_class": "AddressSanitizer",
"pc": 4294981434,
"stop_type": "fatal_error"
}
table.c :
#include "table.h"
#include "entities.h"
static inline entry_t* entryInit(const char* const value){
unsigned int len = strlen(value);
entry_t* entry = malloc(sizeof(entry));
entry->value = malloc(sizeof(char*) * len);
strncpy(entry->value, value, strlen(value));
entry->exists = 1;
entry->occurence = 1;
return entry;
}
table_t* tableInit(const unsigned int size){
table_t* table = malloc(sizeof(table_t));
table->entries = malloc(size*sizeof(entry_t));
table->seed = getPrime();
table->size = size;
table->usedEntries = 0U;
return table;
}
//okay, there is definitely an issue here
table_t* tableResize(table_t* table, const unsigned int newSize){
//most likely wont happen but if there is an overflow then we have a problem
if(table->size > newSize) return NULL;
//create a temp array of the realloced array, then do changes there
entry_t* temp = calloc(newSize,sizeof(entry_t));
table->size = newSize;
//temp pointer to an entry
entry_t *tptr = NULL;
unsigned int pos = 0;
unsigned int index = 0;
while(pos != table->size){
tptr = &table->entries[pos];
if(tptr->exists == 1){
index = hashString(table->seed, tptr->value, table->size, pos);
temp[index] = *entryInit(tptr->value);
temp[index].occurence = tptr->occurence;
break;
}
else pos++;
}
table->entries = temp;
//TODO: change table destroy to free the previous array from the table
free(temp);
return table;
}
//insert works fine, it is efficient enough to add something in the table
unsigned int tableInsert(table_t* table,const char* const value){
//decide when to resize, might create a large enough array to bloat the memory?
if(table->usedEntries >(unsigned int)(2*(table->size/3))) table = tableResize(table, table->size*2);
entry_t* entry = NULL;
unsigned int index;
auto int position = 0;
while(position != table->size){
//calculate the hash of our string as a function of the current position on the table
index = hashString(table->seed,value,table->size, position);
entry = &table->entries[index];
if(entry->exists == 0){
*entry = *entryInit(value);
table->usedEntries++;
return index;
} else if (entry->exists == 1 && strcmp(entry->value, value) == 0){
entry->occurence++;
return index;
} else{
position++;
}
}
}
//there might be an issue here
static inline void tableDestroy(const table_t* const table){
entry_t* entry = NULL;
for (auto int i = 0; i < table->size; ++i){
entry =&table->entries[i];
//printf("Value: %s Occurence: %d Exists: %d \n",entry->value, entry->occurence, entry->exists );
if(&table->entries[i] !=NULL)free(&table->entries[i]);
}
free(table);
}
entities.h :
#pragma once
typedef struct __attribute__((packed)) __entry {
char *value;
unsigned int exists : 1;
unsigned int occurence;
} entry_t;
typedef struct __table {
int size;
int usedEntries;
entry_t *entries;
unsigned int seed;
} table_t;
here is how I read from a file and process the text:
void readFromFile(const char* const fileName, table_t* table){
FILE *fp = fopen(fileName, "r");
if(!fp) fprintf(stderr,"error reading file. \n");
char word[15];//long enough to hold the biggest word in the text?
int position = 0;
char ch;
while((ch = fgetc(fp))!= EOF){
//discard all the ascii chars that are not letters
if(!(ch >= 65 && ch <= 90) && !(ch >= 97 && ch <= 122)){
word[position]= '\0';
if(word[0] == NULL)continue;
tableInsert(table, word);
position = 0;
continue;
}
else word[position++] = ch;
}
}
Any suggestions what is wrong with my code?
I believe resize might have an issue and I am not properly deleting yet because I have had a lot of problems with the memory management.
Thanks in advance!

Extending C Brute Force Algorithm

I need a brute force algorithm over alphanumeric characters.
The code I use just prints all the permutations to the standard output. I tried for hours but failed to rewrite the code in such a manner that I can just call a function brute_next() to get the next codeword when needed.
Can someone help me rewrite this code? The function brute_next() should return a char* or alternatively gets an char* as parameter. I'm using CLion with gcc under Mac.
The code is (source):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static const char alphabet[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
static const int alphabetSize = sizeof(alphabet) - 1;
void bruteImpl(char* str, int index, int maxDepth)
{
for (int i = 0; i < alphabetSize; ++i)
{
str[index] = alphabet[i];
if (index == maxDepth - 1) printf("%s\n", str);
else bruteImpl(str, index + 1, maxDepth);
}
}
void bruteSequential(int maxLen)
{
char* buf = malloc(maxLen + 1);
for (int i = 1; i <= maxLen; ++i)
{
memset(buf, 0, maxLen + 1);
bruteImpl(buf, 0, i);
}
free(buf);
}
int main(void)
{
bruteSequential(3);
return 0;
}
This is my non-working attempt to convert the recursion into a generator. Just can't figure out how the permutation algorithm works.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char alphabet[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"
"$%&/()=.-_;!+*#";
static const int alphabetSize = sizeof(alphabet) - 1;
struct bruteconfig {
int index;
int i1;
int i2;
char* str;
int maxDepth;
};
static struct bruteconfig* config;
void brute_init(int maxLen){
free(config);
config = malloc(sizeof(struct bruteconfig*));
config->i1 = 1;
config->i2 = 0;
config->index = 0;
config->maxDepth = maxLen;
}
void bruteImpl()
{
if(config->i2 > alphabetSize) // how to transform for to iterative?
config->i2 = 0;
config->str[config->index] = alphabet[config->i2];
if (config->index == config->maxDepth - 1) {
//printf("%s\n", config->str);
return; // str filled with next perm
}
else {
config->index++;
//bruteImpl(config->str, config->maxDepth);
}
config->i2++;
}
char* bruteSequential()
{
config->str = malloc(config->maxDepth + 1);
if(config->i1 >= config->maxDepth)
return NULL;
memset(config->str, 0, config->maxDepth + 1); // clear buf
bruteImpl(config->str, config->i1); // fill with next perm
return config->str;
//free(buf); // needs to be done by the caller
}
You're trying to switch from recursion to using a generator: the key difference is that recursion stores working state implicitly in the call stack, while a generator needs to store all its state explicitly for the next call.
So, first you need to think about what state is being implicitly held for you in the recursive version:
each level of your recursive call has its own value for the parameter index
each level has its own value for the local variable i
... and that's it.
You have maxDepth levels, numbered 0..maxDepth-1, each with its own current position in the alphabet. Note that the index argument is also just the position in this collection, so you don't need to store it separately.
Now, you need to store some persistent state between calls, and it's going to be this array of maxDepth integer alphabet positions. Can you figure out how to write a function to convert that array into a string? Can you figure out how to advance the state one place in the same way your recursive code would?
Edit your state should probably look something like
struct PermutationState {
/* stringLength == maxDepth */
int stringLength;
char *string;
/* better to avoid globals */
int alphaLength;
const char *alphabet;
/* this replaces i as the index into our alphabet */
int *alphaPos;
};
and I'd suggest writing an interface like
struct PermutationState* start_permutation(int stringLength,
int alphaLength,
const char *alphabet)
{
struct PermutationState *state = malloc(sizeof(*state));
if (!state) return NULL;
/* initialize scalar values first, for easier error-handling */
state->stringLength = stringLength;
state->string = NULL;
state->alphaLength = alphaLength;
state->alphabet = alphabet;
state->alphaPos = NULL;
/* now we can handle nested allocations */
state->string = malloc(stringLength + 1);
state->alphaPos = calloc(stringLength, sizeof(int));
if (state->string && state->alphaPos) {
/* both allocations succeeded, and alphaPos is already zeroed */
memset(state->string, alphabet[0], stringLength);
state->string[stringLength] = 0;
return state;
}
/* one or both of the nested allocations failed */
end_permutation(state);
return NULL;
}
void end_permutation(struct PermutationState *state)
{
free(state->string);
free(state->alphaPos);
free(state);
}
and finally you're looking to implement this function:
char *next_permutation(struct PermutationState *state)
{
/* TODO */
}
Since start_permutation has already set you up with state->alphaPos = [0, 0, ... 0] and state->string = "aaa...a", you probably want to advance alphaPos by one position and then return the current string.
NB. I assumed you don't need to copy the alphabet, which means the caller is responsible for guaranteeing its lifetime. You could easily copy that too, if necessary.
I just can't figure out how the permutation algorithm works
It's quite simple: To get from one word to the next, start at the rightmost position, change that character to the next in the alphabet; if there's no next character, reset the position to the first character in the alphabet and continue with changing the position to the left; if there's no position left, the codeword needs to be lengthened. Here's a sample implementation:
char *brute_next()
{
for (; ; )
{
static char *buf; // buffer for codeword
static int maxDepth; // length of codeword
int i, index = maxDepth-1; // alphabet and buffer index, resp.
while (0 <= index) // as long as current length suffices:
{ // next char at buf[index] is next in alphabet or first:
i = buf[index] ? strchr(alphabet, buf[index]) - alphabet + 1 : 0;
if (buf[index] = alphabet[i]) return buf;
buf[index--] = alphabet[0]; // reset to 'a', continue to the left
}
index = maxDepth++; // now need to lengthen the codeword
buf = realloc(buf, maxDepth+1); // string length + terminator
if (!buf) exit(1);
buf[index] = buf[maxDepth] = '\0';
}
}

I attempted to parse a string into different words, attempted to freed them later but 2 of the strings have the same byte addresses

I am currently trying to parse a string into an array of strings.
So far, I currently believe I've succeeded in splitting up the string by inserting '\0' after every word "chunk".
However, when I attempt to free the string array later, some of my words have the same byte address, and thus, when I try to free one of them, the other gets freed as well.
This is the code for my parser, I apologize for its messy form:
/*
* parser()
*
* Parses a given string into different words and returns a list with the words.
* If there is a non-space and non-alphabetic character an error is recorded.
*/
void parser(char* str, char** actualList, char** freeingList,char* error, int* length){
// initialize variables
bool chara = false;
bool beginning = true;
int size = strlen(str);
bool nonAlphaSpace = false;
// iterate through the entire string
for(int i = 0; i < size; i++){
// if the character is not either a space or an alphabetic character
if(isspace(str[i])==0 && isalpha(str[i])==0 && !nonAlphaSpace){
*error = str[i];
nonAlphaSpace = true;
}
}
// if there was no irregular character
if(!nonAlphaSpace){
for(int j = 0; j < size; j++){
// if the character is the beginning of the current string
if(beginning){
// record this string into the list of words
freeingList[*length] = &str[j];
(*length)++;
// set the status of any alphabetic character being present to false;
chara = false;
// if the current character is an alphabetic character
if(isalpha(str[j])!=0){
chara = true;
}
beginning = false;
}
// if the character is a space
else if(isspace(str[j])!=0){
// if there was a character beforehand
if(chara){
// get the pointer to the next character
char* new = &str[j+1];
// change the current character to a null
str[j] = '\0';
// realign the pointer to the string to rest of the string
str = new;
j = -1;
size = strlen(str);
beginning = true;
}
}
// if the character is an alphabetic character
else{
chara = true;
}
}
// if the last chunk of string left didn't contain any characters
if(!chara){
free(str);
}
// for every word extracted
for(int k = 0; k < *length; k++){
int newSize = strlen(freeingList[k]);
bool first = true;
// get the pointer to the first character in the word, i.e. not the first few spaces
for(int l = 0; l < newSize; l++){
if(isspace(freeingList[k][l])==0 && first){
actualList[k] = &freeingList[k][l];
first = false;
}
}
}
}
}
This is when I attempt to free it:
// free the current collection of strings
for(int j = 0; j < size; j+=2){
free(words[j]);
}
When I input "home or for" into the parser and later try to free it, the address of "home" is 0x7fffffffe840 while the address of "for" is 0x7fffffffe848. This leads me to believe that the freeing of home also frees or causing a SIGABRT error later.
Is this assumption correct? How can I overcome this double freeing?
You should only call free() on pointers returned by malloc(), calloc(), or realloc(). What it looks like you are doing:
char *ptr = malloc(100);
char *ptr2 = &ptr[10];
free(ptr2); // You can't do that.
I suspect you meant to make a copy of the strings. Here's a simplified version:
void parser(char* str, char** actualList, int* length) {
char *start = str; // The start of the current string
int count = 0; // Number of strings copied
while (*str) {
if (isspace(*str)) {
*str = '\0';
actualList[count] = malloc(strlen(start) + 1); // Allocate space for string
strcpy(actualList[count++], start); // Copy string
start = str + 1; // Reset for next string
if (count == *length - 1) break; // Don't overflow pointer array
}
str++;
}
// Grab the final string
actualList[count] = malloc(strlen(start) + 1); // Allocate space for string
strcpy(actualList[count++], start); // Copy string
*length = count;
}
Then call it like:
char input[] = "home or for";
char *words[5];
int max_words = 5;
parser(input, words, &max_words);
// max_words should be 3 now
for (int i = 0; i < max_words; i++) {
printf("%s\n", words[i]);
}
// Clean up
for (int i = 0; i < max_words; i++) {
free(words[i]);
}
Output:
home
or
for
That's not a parser, though. More a tokenizer.
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
bool parser(char const *str, char ***words, size_t *num_words, size_t *error)
{ // ^^^ gaaaah! *)
assert(words);
errno = 0;
size_t length = strlen(str);
for (size_t i = 0; i < length; ++i) {
if (!isalnum(str[i]) && !isspace(str[i])) {
*error = i; // the position is most likely more meaningful than the character
return false; // get outta here!!
}
}
char const *begin;
char const *end;
*num_words = 0;
*words = NULL;
bool in_word = false;
for (size_t i = 0; i <= length; ++i) {
if (!in_word && isalnum(str[i])) { // word begins
begin = str + i;
in_word = true;
}
else if (in_word && !isalnum(str[i])) { // word ended
end = str + i;
char *word = calloc(end - begin + 1, sizeof *word);
if (!word) {
for (size_t i = 0; i < num_words; ++i)
free((*words)[i]);
free(*words);
errno = ENOMEM;
return false;
}
memcpy(word, begin, end - begin);
char **tmp = realloc(*words, (*num_words + 1) * sizeof *tmp);
if (!tmp) {
free(word);
for (size_t i = 0; i < num_words; ++i)
free((*words)[i]);
free(*words);
errno = ENOMEM;
return false;
}
*words = tmp;
tmp[(*num_words)++] = word;
in_word = false;
}
}
return true;
}
int main(void)
{
char const *foo = "slfkja askdfj jk j aksjf lasjdflkjsdlf jask fdjl";
char **words = NULL;
size_t num_words = 0;
size_t error = 0;
if (!parser(foo, &words, &num_words, &error)) {
if (errno == ENOMEM)
fputs("Not enough memory. :(\n\n", stderr);
else fprintf(stderr, "Error at position %zu: \"%s\"\n\n", error, foo + error);
return EXIT_FAILURE;
}
puts("List of words:");
for (size_t i = 0; i < num_words; ++i) {
printf("\"%s\"\n", words[i]);
free(words[i]);
}
free(words);
}
C should be renamed brainf*ck ...
*) Three Star Programmer
you modify the value of str in the body of the function (in the line str = new; (don't use new as an identifier, more if you plan to use this code as C++ code, as new is a reserved word in C++). As you don't call malloc(3) in the function body, it's quite normal you get a problem from free(3), as free requires to be passed a pointer previously generated with malloc (and only once, so you cannot call it twice with the same pointer). This is the reason of you getting SIGABRT and the like. As a general rule, don't call free(3) in a function you don't also call malloc for the same pointer. That use is error prone and you will run into trouble more than once a day if you insist in doing everything in a single function.
better than apologize for the messy form of the code, please, clean it before posting. Post a minimu (meaning the minimum code that shows the error), full (meaning that we can compile it and observe the result you post as failing), verifiable (code that shows it producing the observed result, and not the expected one) and complete (this means we have nothing to do but compile it and run) code (so we can test it failing as you say, without having to correct it first) That way, we can make a diagnostic of what happens in your code. If we need to correct the code just to make it runnable, we can correct the main problem you are observing and be unable to see the mistake. You see? :)
Note about using new as an identifier in C code:
Many Unit Testing frameworks require your code to be compilable as C++ code, so it can be used by the framework (at least Google Test requires this) If you plan to write unit tests for your code, remember that new is a reserved word in C++ for the operator new, and so, your code will produce syntax errors if you try to compile it with a c++ compiler. Better if you don't use it.

using functions in c (return value)

Learning C and having many doubts.
I have a function (lets say function 1) that calls another function (lets say function 2).
Function 2 calculates an array of string.
How can I use this array in function 1?
Some code example:
int find_errors(char* word)
{
char error[100];
/*Given the word, It will find the duplicate chars and store it in the
error array. */
return 0;
}
int find_word(char* word)
{
find_errors (word);
printf("%s\n", error);
return 0;
}
There are at least three possible approaches:
Use a global variable
pass a parameter between them
return a pointer from the function
There are multiple ways to do this.
1) Create a dynamic array and return a pointer to the array. This will require you to manually free the memory for the array at a later time.
#define NUM_ELEMS 50
// In find_error():
char* error = malloc(NUM_ELEMS * sizeof(char));
return error;
// In find_word():
char *error = find_errors();
// do stuff
free(error);
2) Pass a pointer to find_errors that it can use as the error array. This will not require you to manually free the memory.
// In find_word():
char error[NUM_ELEMS];
find_error(error);
3) Use a global array. May make it more difficult for other people to understand your code. Has other potential problems as well.
// In global scope:
char error[NUM_ELEMS];
Your question relates to "call-by-reference" and "call-by-value".
char* getNewValsToSet(void)
{
char* new_vals = (char*) malloc(sizeof(char[5]));
new_vals[4] = '\0';
return new_vals;
}
void setValuesEven(char* vals_to_set)
{
vals_to_set[0] = 'A';
vals_to_set[2] = 'C';
}
void setValuesOdd(char* vals_to_set)
{
vals_to_set[1] = 'B';
vals_to_set[3] = 'D';
}
int main(void)
{
char* some_vals_to_set = getNewValsToSet();
setValsEven(some_vals_to_set);
setValsOdd(some_vals_to_set);
// ... now has vals "ABCD"
free(some_vals_to_set); //cleanup
return 0;
}
If you have "doubts" about learning C, IMHO it's one of the best things you can do (no matter the language in which you work) because it will explain exactly how things work "under-the-hood" (which all high-level languages try to hide to some degree).
You need to declare the error array globally and use it just like you did.
EDIT: using global variables isn't the best practice in most of the cases, like this one.
Here is an example of what you are looking for with an awesome console output. It dynamically allocates the array to hold any number errors (duplicate characters in your case) that may occur.
//Only free errors if result is > 0
int find_errors(char* word, char** errors)
{
int num_errors = 0;
int word_length = strlen(word);
int ARRAY_SIZE = MIN(8, word_length);
char existing[word_length];
int existing_index = 0;
*errors = NULL;
for(int i = 0; i < word_length; i++)
{
char character = word[i];
//Search array
for (int n = 0; n < word_length; ++n ) {
if(n >= existing_index)
{
existing[n] = character;
existing_index++;
break;
}
if (existing[n] == character) {
num_errors++;
if(!*errors)
*errors = (char*)malloc(ARRAY_SIZE * sizeof(char));
//Check if we need to resize array
if(num_errors >= ARRAY_SIZE)
{
ARRAY_SIZE *= 2;
ARRAY_SIZE = MIN(ARRAY_SIZE, word_length);
char *tmp = (char*)malloc(ARRAY_SIZE * sizeof(char));
memcpy(tmp, *errors, (unsigned long)ARRAY_SIZE);
free(*errors);
*errors = tmp;
}
//Set the error character
(*errors)[num_errors - 1] = character;
break;
}
}
}
return num_errors;
}
int find_word(char* word)
{
char* errors;
int errCount = find_errors (word, &errors);
if(errCount > 0)
{
printf("Invalid Characters: ");
for(int i =0; i < errCount; i++)
{
printf("%c ", errors[i]);
}
printf("\n");
free(errors);
}
return 0;
}
int main(int argc, char *argv[])
{
find_word("YWPEIT");
find_word("Hello World");
find_word("XxxxXXxXXoooooooOOOOOOOOOOOOOOOooooooooOOOOOOOOOOOOooooooOOO");
}

Pointers and getstring function

I am trying to write a function to get a string from uart. Its for an embedded system so I don't want to use malloc.
The pointer that is passed to the getstring function seems to point to garbage after the gets_e_uart1() is called. I don't use pointers too often so I'm sure it is something really stupid and trivial that Im doing wrong.
int main()
{
char *ptr = 0;
while(1)
{
gets_e_uart1(ptr, 100);
puts_uart1(ptr);
}
return 0;
}*end main*/
//-------------------------------------------------------------------------
//gets a string and echos it
//returns 0 if there is no error
char getstring_e_uart1(char *stringPtr_, const int SIZE_)
{
char buffer_[SIZE_];
stringPtr_ = buffer_;
int start_ = 0, end_ = SIZE_ - 1;
char errorflag = 0;
/*keep geting chars until newline char recieved*/
while((buffer_[start_++] = getchar_uart1())!= 0x0D)
{
putchar_uart1(buffer_[start_]);//echo it
/*check for end of buffer
wraparound if neccesary*/
if(start_ == end_)
{
start_ = 0;
errorflag = 1;
}
}
putchar_uart1('\n');
putchar_uart1('\r');
/*check for end of buffer
wraparound if neccesary*/
if(start_ == end_)
{
buffer_[0] = '\0';
errorflag = 1;
}
else
{
buffer_[start_++] = '\0';
}
return errorflag;
}
Update:
I decided to go with approach of passing a pointer an array to the function. This works nicely, thanks to everyone for the informative answers.
Updated Code:
//-------------------------------------------------------------------------
//argument 1 should be a pointer to an array,
//and the second argument should be the size of the array
//gets a string and echos it
//returns 0 if there is no error
char getstring_e_uart1(char *stringPtr_, const int SIZE_)
{
char *startPtr_ = stringPtr_;
char *endPtr_ = startPtr_ + (SIZE_ - 1);
char errorflag = 0;
/*keep geting chars until newline char recieved*/
while((*stringPtr_ = getchar_uart1())!= 0x0D)
{
putchar_uart1(*stringPtr_);//echo it
stringPtr_++;
/*check for end of buffer
wraparound if neccesary*/
if(stringPtr_ == endPtr_)
{
stringPtr_ = startPtr_;
errorflag = 1;
}
}
putchar_uart1('\n');
putchar_uart1('\r');
/*check for end of buffer
wraparound if neccesary*/
if(stringPtr_ == endPtr_)
{
stringPtr_ = startPtr_;
*stringPtr_ = '\0';
errorflag = 1;
}
else
{
*stringPtr_ = '\0';
}
return errorflag;
}
Hint: ptr is pointing to garbage before gets_e_uart1() is called.
You need to pass a pointer to your pointer to gets_e_uart1()
EDIT: Except ... if you're trying to have ptr in main() point to the buffer_ in your function ... you've got another problem. buffer_ is on the stack and is out of scope as soon as the function returns. You would need to malloc() that memory in your function.
char getstring_e_uart1(char **stringPtr_, const int SIZE_)
{
char *buffer_ = (char*) malloc(SIZE_ * sizeof(char));
*stringPtr_ = buffer_;
(Editing again because I wasn't paying attention to your main loop, sorry)
Then you're going to have to free it after calling puts_uart1(ptr) which means you mallocing and freeing constantly in that loop. It seems you have a fixed size for that buffer, why not just create it in main() and pass it into both functions?
In addition to Brian's answer I think you also have a problem here:
char getstring_e_uart1(char *stringPtr_, const int SIZE_)
{
char buffer_[SIZE_];
stringPtr_ = buffer_;
after the function returns buffer is no longer valid but stringPtr_ would still point to it. You could make buffer_ static or allocate it globally
You need to construct the buffer prior to invoking getstring_e_uart1(). The code as written will cause the buffer_ variable to be destroyed when the function exits.
I think you want something more like:
char buffer_[SIZE_];
while(1) {
char* ptr = buffer_;
gets_e_uart1(ptr, sizeof(buffer_));
puts_uart1(ptr);
}
Note: I've done no verification regarding the reuse of the variable buffer_.
You don't need to make the buffer static or global - you just have to have the caller allocate it. The changes are trivial:
int main()
{
while(1)
{
char buffer[100] = { 0 };
gets_e_uart1(buffer, sizeof buffer);
puts_uart1(buffer);
}
return 0;
}
//-------------------------------------------------------------------------
//gets a string and echos it
//returns 0 if there is no error
char getstring_e_uart1(char *buffer_, const int SIZE_)
{
int start_ = 0, end_ = SIZE_ - 1;
char errorflag = 0;
/* ... */

Resources