Exception thrown: read access violation - c

i'm a beginner and my english is not well so sorry first. im trying to sum the numbers in a string (for a14fg5pk145 it returns 14+5+145), and it doesn't work:
"Exception thrown: read access violation.
str was 0x61."
this i my code:
void main()
{
int x, i;
char* pp;
char buffer[SIZE];
printf("Please enter numbers and letters:\n");
gets(buffer);
pp = buffer;
x = SumStr(*pp);
printf("%d", x);
}
int SumStr(char* str)
{
int sum=0, num=0, flag = 0;
while ((*str) != '\0')
{
while (((*str) > '1') && ((*str) < '9'))
{
if (flag == 0)
{
num += (*str);
flag = 1;
}
else if (flag == 1)
num = num * 10 + (*str);
str++;
}
if (flag == 0)
str++;
sum += num;
num = 0;
flag = 0;
}
return sum;
}

First problem with your code which is causing Exception.
x = SumStr(*pp);
it should be
x = SumStr(pp);
Because you should pass address of the string pointer not its first character by attaching asterix.
Second Issue that will not make it work is.
num += (*str);
and
num = num * 10 + (*str);
By (*str) you are actually adding the character ascii value instead of number.
This will solve the problem by changing the ascii value to number.
num += (*str) - '0';
num = num * 10 + (*str) - '0';

This may serve your purpose
#include<stdio.h>
#include<string.h>
int main()
{
int i, sum = 0, store;
char str[] = "a14fg5pk145asdasdad6";
int length = strlen(str);
for(i = 0; i < length; i++) {
store = 0;
while(isdigit(str[i])) {
store = (store * 10) + (str[i] - '0');
i++;
}
sum += store;
}
printf("%d\n", sum);
return 0;
}
output :
170

Pass pp, not *pp, to the function SumStr. *pp has the type char, and the function expects char *. In fact, you do not even need pp at all, just pass the buffer as the parameter.
Also:
Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security. Use fgets() instead.

Related

Compute the most frequent digit in a string of digits in C

I am trying to compute the most frequent digit in a string of characters, and I need to use pointers but I am not sure how to go about this with pointers.
int most(char* string){
int counter = 0;
int* array =(int*) malloc(sizeof(int)*10);
char* original = string;
while(*original){
counter++;
string++;
//Not sure what to put in this loop
}
}
for example, I want to call the code
char nums[] = "132433423";
printf("%d \n",most(nums));
// 3
The specification for your function is incomplete:
can the string contain non-digit characters?
what should be returned if there are no digits at all?
which value should be returned if there are multiple digits with the same maximum number of occurrences?
should the function return the digit or its numeric value? Your main() function uses the latter, but it is not clear from the text of the question.
The most function receives a pointer to the string. You can write a loop where you handle one character at a time and increment the pointer for the next iteration until you reach the end of the string. You must also decide what to return if the string contains no digits.
Here is a simple example:
int most(const char *s) {
int count[10] = { 0 };
int res, i, max;
while (*s) {
if (*s >= '0' && *s <= '9')
count[*s - '0']++;
s++;
}
res = -1; /* return -1 if no digits */
max = 0;
for (i = 0; i < 10; i++) {
if (count[i] > max)
res = i;
}
return res;
}
If you are restricted from using any array at all, allocating a block of memory seems indeed a good solution:
int most(const char *s) {
int *count = calloc(sizeof(*count), 10);
int res, i, max;
while (*s) {
if (*s >= '0' && *s <= '9')
*(count + *s - '0') += 1;
s++;
}
res = -1; /* return -1 if no digits */
max = 0;
for (i = 0; i < 10; i++) {
if (*(count + i) > max)
res = i;
}
free(count);
return res;
}
The notation *(count + *s - '0') += 1 works this way: count is a pointer to an array of int allocated and initialized to 0 by calloc. *s - '0' is the digit value n of the character pointed to by s, that has been tested to be a digit. count + *s - '0' is a pointer to the n-th entry in the array. *(count + *s - '0') += 1 increments this value by one.
There are ways to do this without memory allocation, with 10 variables and explicit tests for the different digits, but I doubt this be the expected solution.
If you can explain your choices to your teacher, there are 2 ways to use arrays without the [ and ] characters. These are obsolescent features of the C Standard, which most programmers are not familiar with, and which you can ignore unless you are curious:
int most(const char *s) { /* version with C99 digraphs */
int count<:10:> = { 0 };
int res, i, max;
while (*s) {
if (*s >= '0' && *s <= '9')
count<:*s - '0':>++;
s++;
}
res = -1; /* return -1 if no digits */
max = 0;
for (i = 0; i < 10; i++) {
if (count<:i:> > max)
res = i;
}
return res;
}
Or
int most(const char *s) { /* version with old-style trigraphs */
int count??(10??) = { 0 };
int res, i, max;
while (*s) {
if (*s >= '0' && *s <= '9')
count??(*s - '0'??)++;
s++;
}
res = -1; /* return -1 if no digits */
max = 0;
for (i = 0; i < 10; i++) {
if (count??(i??) > max)
res = i;
}
return res;
}
You could first sort the string so that the smaller digit characters appear first in num. You could use qsort() (from stdlib.h) like
int cmpfn(const void *a, const void *b)
{
int x = *(char *)a;
int y = *(char *)b;
return x-y;
}
int main()
{
char nums[] = "132433423";//"111222223333";//
qsort(nums, sizeof(nums)/sizeof(nums[0]) -1, sizeof(nums[0]), cmpfn);
printf("\nAfter sorting: %s", nums);
. . . . . . . . . .
. . . . . . . . . .
}
Declare variables to store the mode (ie, the value that appears most frequently in the data) and the frequency of the mode value.
int mode=-1, modecount=-1, n;
Now find the frequency of each digit character. Since this is a sorted character array, the same value will appear consecutively.
for(char *ptr=nums, *lptr=NULL; *ptr; ptr+=n)
{
lptr = strrchr(ptr, *ptr);
n = lptr - ptr + 1;
if(n>modecount)
{
printf("\n%c", *ptr);
modecount = n;
mode = *ptr;
}
}
printf("\nMode is: %c", mode);
strrchr() (from string.h) will find the last occurrence of a character in a string.
#include<string.h>
int most (char* nums) {
int i, max_index = 0;
int digit_dictionary[10]={0,0,0,0,0,0,0,0,0,0};
for (i=0; i< strlen(nums); i++) {
digit_dictionary[nums[i]-'0'] ++;
}
for (i=1; i<10; i++) {
if (digit_dictionary[i]> digit_dictionary[max_index])
max_index = i;
}
return max_index;
}
I will try to be as elaborate as I can:
You create a dictionary in which each index corresponds to a digit that can occur (0-9). Then, iterate through the string(which is basically an array of characters, and store each digit to its corresponding index in dictionary.
Note: [nums[i]-'0'] is calculated into the index of the dictionary since each char has an integer value (look up ASCII table). The counter at that index is incremented to keep count of number of occurrences of that digit.
After that, go through the dictionary to determine at which position is the digit with most occurrences, and return that digit.
I'm not sure what you mean by "using pointers", but here's a version which doesn't use pointers except for walking the input string:
char most_frequent_character(char *s)
{
int freq[10];
int max_freq;
int max_idx;
int idx;
while(*s)
freq[*s++ - '0']++; /* compute character freqs */
max_idx = 0;
max_freq = freq[0];
for(idx = 1 ; idx < 10 ; ++idx)
if(freq[idx] > max_freq)
{
max_freq = freq[idx];
max_idx = i;
}
return '0' + max_idx;
}
Have fun.
EDIT
To convert the above to "use pointers":
A. Change freq to a pointer-to-int and initialize it using malloc; in addition, initialize the memory pointed to by freq using memset:
int *freq = malloc(sizeof(int) * 10);
memset(freq, 0, sizeof(int)*10);
B. In the "compute character freqs" loop, use pointer references instead of indexing:
while(*s)
{
*(freq + (*s - '0')) = *(freq + (*s - '0')) + 1;
s++;
}
C. Use a pointer ref to set the initial value of max_freq:
max_freq = *freq;
D. In the for loop, use pointer math instead of indexing:
for(idx = 1 ; idx < 10 ; ++idx)
if( *(freq + idx) > max_freq)
{
max_freq = *(freq + idx);
max_idx = i;
}
E. Free the memory allocated earlier before the return statement:
free(freq);
return '0' + max_idx;
Now, sit down and understand why things are done in the way that they are here. For example, why didn't I do the following when computing the character frequencies?
while(*s++)
*(freq + (*s - '0')) = *(freq + (*s - '0')) + 1;
or
while(*s)
*(freq + (*s++ - '0')) = *(freq + (*s++ - '0')) + 1;
Each of the above would save several lines of code - why shouldn't they be used? (The obvious answer is "because they won't work as intended" - but WHY?)
Best of luck.

Int pointers having weird behavior in C

void main(){
int digits[21]; //this was initialized so that every element is 0 by looping over every element and setting it to 0
char input[20];
scanf("%s", input);
parseDigits(digits, input);
}
void parseDigits(int* digits, char *string){
char *end = string + strlen(string) -1;
int i;
for (i = 0; i < strlen(string) - 1; i++, end--){
int *digit = digits + i;
printf("%d", *digit);
*digit += charToDigit(*end);
if (*digit >= 10){ //carry one
*digit -= 10;
digit++;
*digit += 1;
}
}
}
Prints an excessively large integer, instead of 0, which is the expected output. I don't understand since
digits + i
should still be within the range of the array.
There can be other issues, but from first glance you have not initialized your array properly, which should have been done like:
int digits[21] = { 0 };

Caesar code in C extra letter for result

#include <stdio.h>
void caesar(char bemenet[], char eredmeny[], int n){
int i = 0;
for(i = 0; bemenet[i] != '\0'; i++) {
if(bemenet[i] == 'z') {
eredmeny[i] = 'a';
eredmeny[i] += n-1;
}
else
{
eredmeny[i] += n;
}
}
eredmeny[i] = '\0';
}
int main(){
char tomb1[]="caesarkodolas";
char tomb2[]="";
caesar(tomb1,tomb2,1);
printf("%s \n",tomb2);
return 0;
}
My out for the "eredmeny" (result) this:
"dbftbslpepmb" but tomb2=> ☺dbftbslpepmb it's not OK.. cause I have an extra char |☺|..
Allocate enough memory for the second parameter, and change this line
eredmeny[i] += n;
to this:
eredmeny[i] = bemenet[i] + n;
Note that this is not a bulletproof implementation of Caesar cipher: it would work for n==1, but it will break for larger n.
You need to think of a different way of implementing the "wrap-around": rather than testing for 'z' and replacing it with 'a', compute the new position of a letter modulo 26, and then add a to it:
void caesar(char bemenet[], char eredmeny[], int n){
int i;
for(i = 0; bemenet[i] != '\0'; i++) {
// Compute the position of the replacement letter
int pos = (bemenet[i] - 'a' + n) % 26;
// Place the letter into the output.
eredmeny[i] = 'a' + pos;
}
eredmeny[i] = '\0';
}
demo.
First of all you should have tomb2 big enough to store result.
For example, as mentioned above
char tomb2[255] = {0};
Also you have error here
else
{
eredmeny[i] += n;
}
You have to assign valid ASCII value to eredmeny[i] so change this string to
eredmeny[i] += bemenet[i] + n
Also it usually bad practice to pass a pointer on array without passing its size. Easy to get buffer overflow.
you're not doing the maths right.
if you are using just lower case letters then you need to add n, but then many letters will be "after" z, so you need to start again at a.
you want something more like this:
for(i = 0; bemenet[i] != '\0'; i++) {
int encrypted = bemenet[i] + n;
if (encrypted > 'z') encrypted = encrypted - 'z' + 'a';
eredmeny[i] = (char)encrypted;
}
(and also fix the output array size as described in other answers here).

Print an int in C without Printf or any functions

I have an assignment where I need to print an integer in C without using printf, putchar, etc. No header files allowed to be included. No function calls except for anything I wrote. I have one function my_char I am using (maybe its wrong) but it prints out a character. I currently have the following code which is printing the number out backwards. Not looking for an answer. Just looking for some direction, some help, maybe I'm looking at it completely wrong.
void my_int(int num)
{
unsigned int i;
unsigned int j;
char c;
if (num < 0)
{
my_char('-');
num = -num;
}
do
{
j = num % 10;
c = j + '0';
my_char(c);
num = num/10;
}while(num >0);
}
Instead of calling my_char() in the loop instead "print" the chars to a buffer and then loop through the buffer in reverse to print it out.
Turns out you can't use arrays. In which case you can figure out the max power of 10 (ie log10) with the loop. Then use this to work backwards from the first digit.
unsigned int findMaxPowOf10(unsigned int num) {
unsigned int rval = 1;
while(num) {
rval *= 10;
num /= 10;
}
return rval;
}
unsigned int pow10 = findMaxPowOf10(num);
while(pow10) {
unsigned int digit = num / pow10;
my_char(digit + '0');
num -= digit * pow10;
pow10 /= 10;
}
One option might be to do this recursively, so the number gets printed out in the right order.
In this case, instead of a do/while loop, you'd have a construction more like this, with a base case of num=0.
if(num==0)
return;
j = num % 10;
c = j + '0';
my_int(num/10);
my_char(c);
Edit: Noticed that you aren't allowed to use recursion. It's a bit ugly, but you could check for the digits in the number, and then loop backwards across the number.
To find the number of digits,
int digitDivide = 1;
int tempNum = num;
while(tempNum>0){
tempNum= tempNum/10;
digitDivide=digitDivide*10;
}
and then use that to loop through the number as follows:
digitDivide = digitDivide/10;
while(digitDivide>0){
tempNum = (num/digitDivide)%10;
c = j + '0';
my_char(c);
digitDivide=digitDivide/10;
}
You can convert an int to char * , char * and display this char* :
char *put_int(int nb)
{
char *str;
str = malloc(sizeof(char) * 4);
if (str == NULL)
return (0);
str[0] = (nb / 100) + '0';
str[1] = ((nb - ((nb / 100 * 100 )) / 10) + '0');
str[2] = ((nb % 10) + '0');
return (str);
}
void put_str(char *str)
{
while (*str)
write(1, str++,1);
}
int main(void)
{
put_str(put_int(42));
return (0);
}

C code to convert hex to int

I am writing this code to convert a hex entry into its integer equivalent. So A would be 10 and B would be 11 etc. This code acts weirdly, in that it seg. faults at random locations and including an extra newline character at times will get it to work. I am trying to debug it, just so I can understand what I am doing wrong here. Can anyone take a look and help me here ? Thanks a lot for your time.
/* Fixed working code for anyone interested */
#include <stdio.h>
#include <stdlib.h>
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
int dec;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
if ( temp[i] == '\0')
{
return ;
}
if (temp[i] == '0' || temp[i] == 'x' || temp[i] == 'X' )
{
printf("0");
answer = temp[i];
}
// compare each temp[i] with all contents in hexchar[]
int j;
int a = temp[i];
for ( j=0; hexchar[j] != '\0'; j++)
{
if ( temp[i] == hexchar[j] )
{
answer *= 16;
answer = answer + 10 + (j/2);
// printf("%d\n",answer );
break;
}
}
}
return answer;
}
main()
{
char *test[] =
{ "bad",
"aabbdd"
"0100",
"0x1",
"0XA",
"0X0C0BE",
"abcdef",
"123456",
"0x123456",
"deadbeef",
"zog_c"
};
int answer=0;
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
printf("main():Number of chars = %d\n",numberOfChars);
int i;
// Go through each character and convert Hex to Integers.
for ( i = 0; i<numberOfChars;i++)
{
// Need to take the first char and then go through it and convert
it.
answer = hextoint(test[i]);
printf("%d\n",answer );
}
}
Let's take a look.
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
printf("In here");
printf("%c\t",temp[i] );
}
return answer;
}
This doesn't seem to even try to do any conversion. It should always return 0, since answer is never assigned any other value. Normally, you'd do something like:
for (i=0; input[i] != '\0'; i++) {
answer *= 16;
answer += digit_value(input[i]);
}
return answer;
Where digit_value (obviously enough) returns the value of an individual digit. One way to do this is:
int digit_value(char input) {
input = tolower(input);
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return -1; // signal error.
}
Then, looking at main:
main()
{
Depending on the "implicit int" rule is generally poor practice, at least IMO. It's much better to specify the return type.
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
This actually calculates the number of strings, not the number of chars.
for ( i = 0; i<=numberOfChars;i++)
Valid subscripts run from 0 through the number of items - 1, so this attempts to read past the end of the array (giving undefined behavior).
This'll work for any number within the unsigned int range, the nice thing is it does not use any other library functions so it is great for micro-controllers where space is tight.
unsigned int hexToInt(const char *hex)
{
unsigned int result = 0;
while (*hex)
{
if (*hex > 47 && *hex < 58)
result += (*hex - 48);
else if (*hex > 64 && *hex < 71)
result += (*hex - 55);
else if (*hex > 96 && *hex < 103)
result += (*hex - 87);
if (*++hex)
result <<= 4;
}
return result;
}
The problem is with calculating numberOfChars part. sizeof test is actually the size of the pointer, not the total length of all characters in your array, so the number returned in your code would be 1, which makes the for loop go to the second index of test (test[1]) which does not have a \0 at the end. Try using strlen for calculating numberOfChars.
This may not me the most optimal method, but it should work without problem.
unsigned int hex_to_int(const char* hex) {
unsigned int result = 0;
size_t len = strlen(hex);
for (size_t i = 0; i < len; ++i) {
char cur_char = tolower(hex[len - i - 1]);
// direct return if encounter any non-hex character.
if (!(isdigit(cur_char) && (cur_char >= 'a' && cur_char <= 'f'));)
return result;
unsigned int char_val = (isdigit(cur_char) ? cur_char - '0' : 10 + cur_char - 'a');
result += round(pow(16, i)) * char_val;
}
return result;
}

Resources