I can't understand why I get the following message for my function below (in Visual Studio 2015).
0xC0000005: Access violation reading location 0x0000002C.
I have read this answer but it does not help me.
What this code is about.
There is a string of ints separated in groups of "index,value" pairs. Indexes are unique. Each group is separated by a semi-colon. Example: 1,2;3,5;2,2;3,4
I am trying to get an array of int with each value at its index.
My code so far extracts the strings and puts it into a char* buffer.
Then I separate the groups of "index,value" by the semi-colons and store them in char** arrayKeyValue, which is a member of struct inputElement . The other struc member is a int representing the number of "index,value" groups in the array. I do this with the function "separateStringBySemicolon".
Then I try to separate each group of "index,value" into a new array, where at each "index" will match its "value". I do this by passing my struct to the function "separateKeyValue". I use strtok_s but I get an error.
The first call to the function below (token2 = strtok_s(arrayOfKeyValue[j], sepComma, &next_token2);) brings the error. I understand that token2 or next_token2 cannot be accessed, but I am not sure. And if so, why?
double* separateKeyValue(struct inputElement* inputElement)
{
int count = inputElement->length;
char** arrayOfKeyValue = inputElement->data;
double* arrayDecimal = malloc(count * sizeof(double));
char sepComma = ','; //wrong should be char sepComma[] = ",";
char* token2 = NULL;
char* next_token2;
printf("Value in arrayofkeyvalue: %s", arrayOfKeyValue[0]);
for (size_t j = 0; j < count; j++)
{
token2 = strtok_s(arrayOfKeyValue[j], sepComma, &next_token2);
unsigned int index;
sscanf_s(token2, "%d", &index);
double value;
sscanf_s(next_token2, "%d", &value);
arrayDecimal[index] = value;
printf("res[%d] = %d\n", index, arrayDecimal[index]);
printf("\n");
}
return arrayDecimal;
}
You are specifying a char constant, sepComma, as the second parameter to strtok_s, where it expects a string of delimiter characters.
(not so) Coincidentally, the ASCII value of ',' is 0x2C.
Related
I'm trying to get to read string input from user and store it in two dim array using pointers.
I'm getting Access violation reading location exception when trying to use those strings.
first I declared char*** that will store pointers for two dim array , then I use for loop to initial two dim array for each cell.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORDLEN 80
#define DEFLEN 200
#define KEYVALUE 2
char*** MallocDic(int dictionarySize);
char** MallocDicElement(char* word, char* definition);
void PrintDictionary(char*** dictionary, int dictionarySize);
int main()
{
int dictionarySize;
printf("Please enter dictionary size\n");
scanf("%d", &dictionarySize);
char*** dictionary = MallocDic(dictionarySize);
int i;
for (i = 0; i < dictionarySize; i++) {
char* inputWord = (char*)malloc(WORDLEN * sizeof(char));
char* inputDef = (char*)malloc(DEFLEN * sizeof(char));
if (inputWord == NULL || inputDef == NULL)
{
printf("Failed to allocate memory!\n");
exit(1);
}
printf("enter word : \n");
scanf("%s", inputWord);
printf("enter definition : \n");
scanf("%s", inputDef);
printf("word : %s ,def : %s\n", inputWord, inputDef);
//dictionary[i] = MallocDicElement(inputWord, inputDef);
//free(inputDef);
free(inputWord);
}
printf("Print Dictionary : \n");
//PrintDictionary(dictionary, dictionarySize);
}
char*** MallocDic(int dictionarySize) {
char*** p;
p = (char***)malloc(dictionarySize * sizeof(char**));
return p;
}
char** MallocDicElement(char* word, char* definition) {
char** p = (char**)malloc(KEYVALUE * sizeof(char*));
int i;
for (i = 0; i < KEYVALUE; i++) {
if (i == 0) {
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word;
}
else {
p[i] = (char*)malloc(DEFLEN * sizeof(char));
p[i] = definition;
}
}
return p;
}
void PrintDictionary(char*** dictionary, int dictionarySize) {
int i = 0, j = 0;
for (i = 0; i < dictionarySize; i++) {
for (j = 0; j < KEYVALUE; j++) {
printf("word : %s\n", dictionary[i][0]);
printf("definition : %s\n", dictionary[i][1]);
}
}
}
The logic breaks in when trying to print the first string.
what am I missing here ?
Thanks for any help.
At least these problems.
Leaked memory
Code allocates memory and saves the pointer to that allocation to p[i] and then copies the pointer word to p[i] in the next line. This loses the pointer returned from malloc().
p[i] = (char*)malloc(WORDLEN * sizeof(char));
p[i] = word; // ???
Much more likely OP wants to copy the string, pointed to by word to the memory pointed to by p[i].
p[i] = malloc(WORDLEN);
strcpy(p[i], word);
More common to allocate only what is needed.
p[i] = malloc(strlen(word) + 1);
strcpy(p[i], word);
Research strdup().
Error checking omitted for brevity.
Do not use "%s", "%[]" without a width in *scanf()
Limit acceptable input to 1 less than the size of the destination array.
"%s" does not read and save spaces
The below will not work to read a definition that contains spaces.
printf("enter definition : \n");
scanf("%s", inputDef); // Stops after first word
Scanning will stop at the first white-space after reading some non-white-space.
Perhaps:
scanf(" %199[^\n]", inputDef);
Check return value of input functions
if (scanf(" %199[^\n]", inputDef) != 1) {
Handle_input_error();
}
Other:
Avoid hard to read & maintain allocation
Rather than cast (not needed) and size to the type (defined someplace else), allocate to the size of the referenced object - no type needed to get wrong.
// p = (char***)malloc(dictionarySize * sizeof(char**));
p = malloc(sizeof p[0] * dictionarySize);
Easier to code right, review and maintain.
At the risk of a non-answer here (not working with your extant code) I would like to suggest you take the time to better structure your data. Even something as simple as:
// A `dictionary` is an array of `capacity` entries, `size` of which are in use.
// Elements are kept in lexicographical order.
struct dictionary
{
struct entry
{
const char * word;
const char * definition;
};
struct entry * entries;
size_t size;
size_t capacity;
};
typedef struct dictionary dictionary;
This makes life about a bazillion times easier when dealing with stuff. You can now create a couple of useful functions:
dictionary * new_dictionary( size_t capacity );
void free_dictionary( dictionary * dict );
This structured nature makes it easier to manage individual parts. In particular, your users can pass the pointer to the dictionary around and never have to worry about it changing. For example, suppose you want to update the dictionary’s capacity:
void set_dicitionary_capacity( dictionary * dict, size_t new_capacity )
{
if (new_capacity < dict->size) return;
struct entry * new_entries = realloc( dict->entries, new_capacity * sizeof dict->entries[0] );
if (!new_entries) return;
dict->capacity = new_capacity;
dict->entries = new_entries;
}
This idea of having functions to interface with your opaque dictionary object is the basis for basic data encapsulation. Doing so makes the using code so much easier:
dictionary * words = new_dictionary( 1000 );
if (!words) fooey();
update_dictionary( words, "hello", "a greeting" );
update_dictionary( words, "world", "the Earth; a planet; any organism’s collective society" );
printf( "There are %zu words in the dictionary.\n", dictionary_size( words ) );
const char * desc = find_word( words, "there" );
printf( "Obi Wan can%s use this dictionary.\n", desc ? "" : "not" );
free_dictionary( words );
Hopefully we can already see how things are easier to grok on every level.
In other words, write code in such a way as to make meaning and structure as clear as possible. This helps to reduce the amount of failure our befuddled minds can generate when writing code.
i want to replace _ (underscore) with white spaces and make the first letter of the name and the surname to upper case while printing the nameList in searchKeyword method.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void searchKeyword(const char * nameList[], int n, const char keyword[])
{
int i,name=0;
char *str;
const char s[2] = " " ;
for(i=0;i<n;i++)
{
char *str = (char *) malloc((strlen(nameList[0])+1)*sizeof(char));
strcpy(str,nameList[i]);
strtok(str,"_");
if(strcmp(keyword,strtok(NULL,"_"))==0) // argument NULL will start string
{ // from last point of previous string
name++;
if(nameList[i] == '_')
strcpy(nameList[i],s);
//nameList[i] = ' ';
printf("%s\n",nameList[i]);
}
}
if(name==0)
{
printf("No such keyword found\n");
}
free(str); //deallocating space
}
int main()
{
char p1[] = "zoe_bale";
char p2[] = "sam_rodriguez";
char p3[] = "jack_alonso";
char p4[] = "david_studi";
char p5[] = "denzel_feldman";
char p6[] = "james_bale";
char p7[] = "james_willis";
char p8[] = "michael_james";
char p9[] = "dustin_bale";
const char * nameList[9] = {p1, p2, p3, p4, p5, p6, p7, p8, p9};
char keyword[100];
printf("Enter a keyword: ");
scanf("%s", keyword);
printf("\n");
searchKeyword(nameList, 9, keyword);
printf("\n");
for (int i = 0; i < 9; i++)
printf("%s\n",nameList[i]);
return 0;
}
Search through the strings and print the ones whose surname part is equal to keyword.
As shown in the example runs below, the strings are printed in “Name Surname” format (the first letters are capitalized).
Output should be like this:
Enter a keyword: james
Michael James
zoe_bale
sam_rodriguez
jack_alonso
david_studi
denzel_feldman
james_bale
james_willis
michael_james
dustin_bale
There is no reason to dynamically allocate storage for your name and surname. Looking at your input, neither will exceed 9-characters, so simply using an array for each of 64-chars provides 6X the storage required (if you are unsure, double that to 128-chars and have 1200% additional space). That avoids the comparatively expensive calls to malloc.
To check whether keyword exists in nameList[i], you don't need to separate the values first and then compare. Simply use strstr (nameList[i], keyword) to determine if keyword is contained in nameList[i]. If you then want to match only the name or surname you can compare again after they are separated. (up to you)
To parse the names from the nameList[i] string, all you need is a single pointer to locate the '_' character. A simple call to strchr() will do and it does not modify nameList[i] so there is no need to duplicate.
After using strchr() to locate the '_' character, simply memcpy() from the start of nameList[i] to your pointer to your name array, increment the pointer and then strcpy() from p to surname. Now you have separated name and surname, simply call toupper() on the first character of each and then output the names separate by a space, e.g.
...
#include <ctype.h>
#define NLEN 64
void searchKeyword (const char *nameList[], int n, const char keyword[])
{
for (int i = 0; i < n; i++) { /* loop over each name in list */
if (strstr (nameList[i], keyword)) { /* does name contain keyword? */
char name[NLEN], surname[NLEN]; /* storage for name, surname */
const char *p = nameList[i]; /* pointer to parse nameList[i] */
if ((p = strchr(p, '_'))) { /* find '_' in nameList[i] */
/* copy first-name to name */
memcpy (name, nameList[i], p - nameList[i]);
name[p++ - nameList[i]] = 0; /* nul-terminate first name */
*name = toupper (*name); /* convert 1st char to uppwer */
/* copy last name to surname */
strcpy (surname, p);
*surname = toupper (*surname); /* convert 1st char to upper */
printf ("%s %s\n", name, surname); /* output "Name Surname" */
}
}
}
}
Example Use/Output
Used with the remainder of your code, searching for "james" locates those names containing "james" and provides what looks like the output you requested, e.g.
$ ./bin/keyword_surname
Enter a keyword: james
James Bale
James Willis
Michael James
zoe_bale
sam_rodriguez
jack_alonso
david_studi
denzel_feldman
james_bale
james_willis
michael_james
dustin_bale
(note: to match only the name or surname add an additional strcmp before the call to printf to determine which you want to output)
Notes On Your Existing Code
Additional notes continuing from the comments on your existing code,
char *str = (char *) malloc((strlen(nameList[0])+1)*sizeof(char));
should simply be
str = malloc (strlen (nameList[i]) + 1);
You have previously declared char *str; so the declaration before your call to malloc() shadows your previous declaration. If you are using gcc/clang, you can add -Wshadow to your compile string to ensure you are warned of shadowed variables. (they can have dire consequences in other circumstances)
Next, sizeof (char) is always 1 and should be omitted from your size calculation. There is no need to cast the return of malloc() in C. See: Do I cast the result of malloc?
Your comparison if (nameList[i] == '_') is a comparison between a pointer and integer and will not work. Your compiler should be issuing a diagnostic telling you that is incorrect (do not ignore compiler warnings -- do not accept code until it compiles without warning)
Look things over and let me know if you have further questions.
that worked for me and has no memory leaks.
void searchKeyword(const char * nameList[], int n, const char keyword[])
{
int found = 0;
const char delim = '_';
for (int i = 0; i < n; i++) {
const char *fst = nameList[i];
for (const char *tmp = fst; *tmp != '\0'; tmp++) {
if (*tmp == delim) {
const char *snd = tmp + 1;
int fst_length = (snd - fst) / sizeof(char) - 1;
int snd_length = strlen(fst) - fst_length - 1;
if (strncmp(fst, keyword, fst_length) == 0 ||
strncmp(snd, keyword, snd_length) == 0) {
found = 1;
printf("%c%.*s %c%s\n",
fst[0]-32, fst_length-1, fst+1,
snd[0]-32, snd+1);
}
break;
}
}
}
if (!found)
puts("No such keyword found");
}
hopefully it's fine for you too, although I use string.h-functions very rarely.
I've been trying to work out exactly what this function's purpose is I've come across..
The code intentionally has bad code practices, so I am trying to figure out if this is one of them.
Here is the function:
void clear_mem(char *memblock, int siz) {
register int i;
for (i=0; i<=siz;i++)
*(memblock+i) = 0;
}
The function is called within the following function:
char *get_argument(char line[], int argno){
char *argument = malloc(512);
char clone[512];
strncpy(clone, line, strlen(line)+1);
int current_arg = 0;
char *splitted = strtok(clone, " ");
while (splitted != NULL){
if (splitted[0] != ':'){
current_arg++;
}
if (current_arg == argno+1){
clear_mem(argument, 512); //Here
strncpy(argument, splitted, strlen(splitted)+1);
return argument;
free(argument);
}
splitted = strtok(NULL, " ");
}
if (current_arg != argno){
argument[0] = '\0';
}
free(argument);
return argument;
}
Thanks in advance!
In this code:
for (i=0; i<=siz;i++)
*(memblock+i) = 0;
memblock+i adds the integer i to the pointer memblock. The result points i elements beyond where memblock points. Since memblock is a pointer to char, the result points i characters beyond where memblock points.
Then *(memblock+i) refers to the character at that address. *(memblock+i) is equivalent to memblock[i]. *(memblock+i) = 0 sets the character to zero.
So the effect of this code is to set all characters indexed by i during the loop to zero. It clears a block of memory.
The for (i=0; i<=siz;i++) causes the loop to iterate with i taking all values from zero up to and including siz. Thus, siz+1 characters will be set to zero.
We can see this is an error because get_argument allocates 512 bytes for argument and then later calls clear_mem(argument, 512), which clears 513 bytes. The resulting behavior is not defined by the C code.
EDIT: So it looks like the problem is that the string that getNum is supposed to convert to a float is not actually a string containing all the characters of the token. Instead it contains the character immediately following the token, which is usually NaN so the atof converts it to 0. I'm not sure why this behavior is occuring.
I'm working on a scanner + parser that evaluates arithmetic expressions. I am trying to implement a method that gets a token (stored as a string) which is a number and turns it into a float, but it always returns 0 no matter what the token is.
I was given the code for a get_character function, which I am not sure is correct. I'm having a little trouble parsing what's going on with it though, so I'm not sure:
int get_character(location_t *loc)
{
int rtn;
if (loc->column >= loc->line->length) {
return 0;
}
rtn = loc->line->data[loc->column++];
if (loc->column >= loc->line->length && loc->line->next) {
loc->line = loc->line->next;
loc->column = 0;
}
return rtn;
}
I used it in my getNum() function assuming it was correct. It is as follows:
static float getNum(){
char* tokenstr;
tokenstr = malloc(tok.length * sizeof(char));
int j;
for(j = 0; j < tok.length; j++){
tokenstr[j] = get_character(&loc);
}
match(T_LITERAL); /*match checks if the given token class is the same as the token
class of the token currently being parsed. It then moves the
parser to the next token.*/
printf("%f\n", atof(tokenstr));
return atof(tokenstr);
}
Below is some additional information that is required to understand what is going on in the above functions. These are details about some struct files which organize the input data.
In order to store and find tokens, three types of structs are used. A line_t struct, a location_t struct, and a token_t struct. The code for these are posted, but to summarize:
Lines contain an array of characters (the input from that line of the
input file), an int for the length of the line, an int that is the
line number as a form of identification, and a pointer to the next
line of input that was read into memory.
Locations contain a pointer to a specific line, and an int that
specifies a specific "column" of the line.
Tokens contain an int for the length of the token, a location describing where the token begins, and token class describing what kind of token it is for the parser.
Code for these structs:
typedef struct line {
char * data;
int line_num;
int length; /* number of non-NUL characters == index of trailing NUL */
struct line * next;
} line_t;
typedef struct {
line_t *line;
int column;
} location_t;
typedef struct {
token_class tc;
location_t location;
int length; /* length of token in characters (may span lines) */
} token_t;
It appears that the default behavior intended is to extract a character and then advance to the next prior to returning.
Yet the function, if the line length is exceeded (or the collumn value isn't initialized to less than the line length) will not advance.
Try this:
if (loc->column >= loc->line->length) {
loc->line = loc->line->next;
loc->column = 0;
return 0;
}
And make sure that the column location is properly initialized.
Personally, I would change the function to this:
int get_character(location_t *loc)
{
int rtn = 0;
if (loc->column < loc->line->length) {
rtn = loc->line->data[loc->column++];
}
if (loc->column >= loc->line->length && loc->line->next) {
loc->line = loc->line->next;
loc->column = 0;
}
return rtn;
}
I'd also use unsigned values for the column and length, just to avoid the possibility of negative array indicies.
I see a number of potential problems with this code:
char* tokenstr;
tokenstr = malloc(tok.length * sizeof(char));
int j;
for(j = 0; j < tok.length; j++){
tokenstr[j] = get_character(&loc);
}
match(T_LITERAL); /*match checks if the given token class is the same as the token
class of the token currently being parsed. It then moves the
parser to the next token.*/
printf("%f\n", atof(tokenstr));
return atof(tokenstr);
You create space for a new token string tokenstr, you copy it but you don't null terminate it after, nor is enough space allocated for a token plus the string terminator \0. And at the end there is a memory leak as tokenstr isn't freeed. I might consider a change to something like:
char* tokenstr;
float floatVal;
/* Make sure we have enough space including \0 to terminate string */
tokenstr = malloc((tok.length + 1) * sizeof(char));
int j;
for(j = 0; j < tok.length; j++){
tokenstr[j] = get_character(&loc);
}
/* add the end of string \0 character */
tokenstr[j] = '\0'
match(T_LITERAL); /*match checks if the given token class is the same as the token
class of the token currently being parsed. It then moves the
parser to the next token.*/
floatVal = atof(tokenstr);
/* Free up the `malloc`ed tokenstr as it is no longer needed */
free(tokenstr);
printf("%f\n", floatVal);
return floatVal;
I am fairly new to the C language and allocating memory/using pointers in general. Anyway, I was experimenting with reading a file, putting those values in a struct, etc. I know exactly what I want to do and of course the program runs but the output is incorrect and some kind of jumbled numbers and letters.
There is a text file with new information for each line. Each line represents one object.
This is how a line in the file might look:
meat sirloin 6.55 8 8.50 4
Overall I want to be able to store all of my PRODUCT objects in an array (so I have an array of structs). So I attempted to allocate memory with a pointer, use a line count, and then send the pointer to a function called read. In read I add each struct to the array via a pointer. The program doesn't crash, the output is just not correct and I have no clue why not. It's prob something with pointers. If anyone could help me I would really appreciate it. Any help at all would be great.
//prototype
void read(pointerToArr);
typedef struct
{
char supType[15];
char prodName[15];
double wholePrice;
int quantWhole;
double retPrice;
int retProdQuantity;
}PRODUCT;
FILE *fr;
int lineCount = 0;
int main()
{
PRODUCT *ptr;
int i;
char check[50];
fr = fopen("ttt.txt", "r");
while(fgets(check, sizeof(check), fr)!= NULL)
{
if(check[0] != '\n')
{
lineCount++;
}
}
// allocate memory for array based on line count.
PRODUCT prodContainter[lineCount];
ptr = (PRODUCT*)malloc(sizeof(PRODUCT)*lineCount);
ptr = prodContainter;
read(ptr);
//print after adding to array via pointer from other
//function. this was a test.
for(i = 0; i < lineCount; i++)
{
printf("%s ", prodContainter[i].supType);
printf("%s ", prodContainter[i].prodName);
printf("%f ", prodContainter[i].wholePrice);
printf("%d ", prodContainter[i].quantWhole);
printf("%f ", prodContainter[i].retPrice);
printf("%d\n\n", prodContainter[i].retProdQuantity);
}
return 0;
}
void read(PRODUCT *pointerToArr)
{
// objective in this method is to read in data from the file, create an object for every line and
// then use the pointer array to add those objects to prodConstainer up above.
char supplyName[15];
char productName[15];
double wholeP = 0;
int quantityWhole = 0;
double retailPrice = 0;
int retailProductQuant = 0;
while(fscanf(fr, "%s %s %lf %d %lf %d", supplyName, productName, &wholeP, &quantityWhole, &retailPrice, &retailProductQuant) == 6)
{
PRODUCT record;
int i;
strcpy(record.supType, supplyName);
strcpy(record.prodName, productName);
record.wholePrice = wholeP;
record.quantWhole = quantityWhole;
record.retPrice = retailPrice;
record.retProdQuantity = retailProductQuant;
for(i = 0; i < lineCount; i++)
{
pointerToArr[i] = record;
}
}
fclose(fr);
}
You never rewind the file, so all the reading after you count the number of lines fails.
What you're printing is just what happens to be in memory.
There are many ways to fix this, of course.
Rewind the file, using rewind()
Close the file and let your read() function (whose name collides with a POSIX standard function, btw) re-open the file. This would also involve removing the scary global variable fr.
Re-structure so you never count the number of lines, by just reading and letting the ptr array grow as necessary (see realloc()).
Also, you should really avoid casting the return value of malloc() in C. This:
ptr = (PRODUCT*)malloc(sizeof(PRODUCT)*lineCount);
is better written as:
ptr = malloc(lineCount * sizeof *ptr);
This does away with the cast, and also uses sizeof on a value of the type pointed at to automatically compute the proper number of bytes to allocate.