Pure Pointer notation in C - c

I have this coding assignment where I have to use pure pointer notation only. I am pretty much finished with it but I just realized that I used an array. I am not allowed to do so, unless I change it into a pointer somehow. That's where I am slightly stuck.
This is my code.
#include <stdio.h>
#include <stdlib.h>
/* Function Prototypes */
int main();
void s1(char *random);
void s2(char *s2_input, int index);
void strfilter(char *random, char *s2_input, char replacement);
int main()
{
for(;;)
{
int s1_index = 41;
char s1_random[s1_index];
s1(s1_random);
printf("\ns1 = ");
puts(s1_random);
printf("s2 = ");
int s2_index = 21;
char s2_input[s2_index];
s2(s2_input, s2_index);
if(s2_input[1] == '\0')
{
printf("Size too small");
exit(0);
}
if(s2_input[21] != '\0' )
{
printf("Size too big");
exit(0);
}
printf("ch = ");
int replacement = getchar();
if(replacement == EOF)
break;
while(getchar() != '\n');
printf("\n");
strfilter(s1_random, s2_input, replacement);
printf("\ns1 filtered = ");
puts(s1_random);
printf("Do you wish to run again? Yes(Y), No(N) ");
int run = getchar();
// or include ctype.h and do:
// run == EOF || toupper(run) == 'N'
if(run == EOF || run == 'N' || run == 'n')
break;
while(getchar() != '\n');
}
}
void s1(char *random)
{
int limit = 0;
char characters;
while((characters = (('A' + (rand() % 26))))) /* random generator */
{
if(limit == 41)
{
*(random + 41 - 1) = '\0';
break;
}
*(random + limit) = characters;
limit++;
}
}
void s2(char *s2_input, int index)
{
char array[21] = "123456789012345678901"; /* populated array to make sure no random memory is made */
char input;
int count = 0;
int check = 0;
while((input = getchar() ))
{
if(input == '\n')
{
*(s2_input + count) = '\0';
break;
}
else if(input < 65 || input > 90)
{
printf("invalid input");
exit(0);
}
*(s2_input + count) = input;
count++;
}
index = count;
}
void strfilter(char *random, char *s2_input, char replacement) /* replacement function */
{
while(*s2_input)
{
char *temp = random;
while(*temp)
{
if(*temp == *s2_input)
*temp = replacement;
temp++;
}
s2_input++;
}
}
My issue is this part I am not sure how to edit this to not include an array, and still have it output the program in the same way.
if(s2_input[1] == '\0')
{
printf("Size too small");
exit(0);
}
if(s2_input[21] != '\0' )
{
printf("Size too big");
exit(0);
}
I tried to take the address of the array at a certain point, and then dereference it with a pointer, however that is still using a array. Which is what I am trying to avoid. Any help would be greatly appreciated!

s2_input[i] can be written as *(s2_input+i) where i is some index.

if ((s2_input[1]) == '\0')
is equivalent to:
if (*(s2 + 1) == '\0')
Which means to dereference the value at s2 (which is the location of the zeroth[0] element), and add one to it.
The same could be done for any other location.

Pointer notation and what is often referred to as Indexed notation (which uses the [ ] subscript operator) are entirely equivalent. Either notion provides the pointer address plus an offset from that pointer address. See C11 Standard - 6.5.2.1 Array subscripting That being array[offset] or *(array + offset)1
For example accessing the first element using *array is shorthand for *(array + 0) which is simply array[0] in indexed notation. The 0 being the offset (in elements of that type) from the original pointer address. (type controls pointer arithmetic)
So array[10] is simply *(array + 10). If array is type char, array[10] is 10-bytes after array address. If array is type int (where an int is 4-bytes), then array[10] is 40-bytes after array address (10-int).
For a 2D array, the notation for arr2d[1][2] would simply be *(arr2d[1] + 2) which expanded further is simply *(*(arr2d + 1) + 2).
So generally array[i] is *(array + i) and arr2d[i][j] is *(*(arr2d + i) + j).
footnotes:
It follows that array[offset] is equivalent to *(array + offset) is equivalent to offset[array].

Related

How to check how many times a word appears in a string in all possible upper and lower case combinations in c

For example: "horse HORSE HORse HoRsE" the word horse appears 4 times. How can i do this in c?
#include<stdio.h>
#include<string.h>
your textmain()
your text{
char str[100];
int i,SL,count=0,flag=0;
printf("Give string:");
gets(str);
SL=strlen(str);
for (i=0;i<SL;i++)
{
if ((str[i]=='h')||(str[i]=='H'))
{
flag++;
}
if ((str[i+1]=='o')||(str[i+1]=='O'))
{
flag++;
}
if ((str[i+2]=='r')||(str[i+2]=='R'))
{
flag++;
}
if ((str[i+3]=='s')||(str[i+3]=='S'))
{
flag++;
}
if ((str[i+4]=='e')||(str[i+4]=='E'))
{
flag++;
}
if (flag==5)
{
count++;
flag=0;
i=i+5;
}
}
printf("There are %d horse in the string",count);
}
your text
it can count when i put horse in any possible combination like the one i gave as an example. But when the words have no space "horsehorse" it only counts the first word. And when i put horse in a sentence like "hello horse how are you today" it counts nothing. (sorry for my english)
You need to make a copy to make sure that haystack is modifiable or not modify it at all. Also, use functions. strnicmp is not universal as does not check if strings have different sizes, but was not needed in this case. You can also add some parameter checks.
char strnicmp(const char *haystack, const char *needle, size_t len)
{
while(len--)
if(tolower((unsigned char)*haystack++) != tolower((unsigned char)*needle++))
return 1;
return 0;
}
size_t count(const char *haystack, const char *needle, int overlap)
{
size_t result = 0;
size_t hsize = strlen(haystack);
size_t nsize = strlen(needle);
for(size_t pos = 0; pos + nsize <= hsize;)
{
if(!strnicmp(haystack + pos, needle, nsize))
{
result++;
pos += overlap ? 1 : nsize;
} else pos++;
}
return result;
}
int main(void)
{
printf("%zu\n", count("horSeHORse", "hORsE",0));
printf("%zu\n", count("horSe is", "hORsE",0));
printf("%zu\n", count("dffd;dfsgd d;lgd;fslg ks;dfl kd;", "hORsE",0));
printf("%zu\n", count("tatatatatata", "tata",0));
printf("%zu\n", count("tatatatatata", "tata",1));
}
https://godbolt.org/z/YzaMrKGfz
Thank you for your answer. But is there a way to do it with out the
use of tolower and strncmp
It is a very good practice to use functions but if you do not want to use standard ones you can always write your own ones;
int mytolower(const int x)
{
if(x >= 'A' && x <= 'Z') return x - ('A' - 'a');
return x;
}
char strnicmp(const char *haystack, const char *needle, size_t len)
{
while(len--)
if(mytolower(*haystack++) != mytolower(*needle++))
return 1;
return 0;
}
Set flag to zero before each check, not only after a successful match.
Do not add anything to i when finding a match. Adding 5 resulted in moving beyond the second “h” in “horsehorse” because the loop adds 1 anyway. There is no need to add anything because the loop adds 1 to i in each iteration, and adding more than 1 is an error because, for some strings, a new match can start before the end of the current match. For example, “yoyoyo” contains two matches for “yoyo”.
You can create a for loop that checks through the word and coverts it into lowercase using tolower.
After that you could use strncmp that compares the words to horse
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main() {
char str[100];
int i,SL,count=0;
printf("Give string:");
fgets(str, sizeof(str), stdin);
str[strcspn(str, "\n")] = '\0';
SL=strlen(str);
for (i = 0; i < SL; i++) {
str[i] = tolower(str[i]);
}
for (i=0; i<SL; i++) {
if (strncmp(str + i, "horse", 5) == 0) {
count++;
i += 4;
}
}
printf("There are %d horse in the string", count);
return 0;
}
Example output 1:
Give string:horsehorse
There are 2 horse in the string
Example output 2:
Give string:hello i am a hORsE
There are 1 horse in the string
A couple issues here:
first off, please don't post incomplete code that doesn't compile.
Also, you're using some unsafe, deprecated functions here that are an accident just waiting to happen: You should change gets to fgets.
For the logic of the program, set flag to 0 outside the if statement and skip manually incrementing i altogether
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 512
int main() {
char str[BUFFSIZE];
int i, SL, count = 0, flag = 0;
printf("Give string:");
fgets(str, BUFFSIZE, stdin);
SL = strlen(str);
for (i = 0; i < SL; i++) {
if ((str[i] == 'h') || (str[i] == 'H')) {
flag++;
}
if ((str[i + 1] == 'o') || (str[i + 1] == 'O')) {
flag++;
}
if ((str[i + 2] == 'r') || (str[i + 2] == 'R')) {
flag++;
}
if ((str[i + 3] == 's') || (str[i + 3] == 'S')) {
flag++;
}
if ((str[i + 4] == 'e') || (str[i + 4] == 'E')) {
flag++;
}
if (flag == 5) {
count++;
}
flag = 0;
}
printf("There are %d horse in the string", count);
}

Changing Array Notation to pure pointer notations

I had this school project that I'm working on. I am done, I just need to edit it a bit and am running into a issue. I sent my code to my professor so he could check it over and there's only one thing wrong with it.
All your array notations need to change to pure pointer notations such as *s1 or s1++, etc. nothing like *(random + 41 - 1) or *(s2_input + count) - you need to update your pointer and use dereference (exactly what you are doing in strfilter function.
He wouldn't explain further, so I am just confused on how exactly I would change my code. I have figured out my code is still in a array notation in a couple spots but any help would be appreciated.
Such as *(random + 41 - 1) = '\0'; , *(s2_input + count) = '\0'; , and *(s2_input + count) = input;. What can I do to fix this?
#include <stdio.h>
#include <stdlib.h>
/*Function Prototypes*/
int main();
void s1(char *random);
void s2(char *s2_input, int index);
void strfilter(char *random, char *s2_input, char replacement);
int main()
{
for(;;)
{
int s1_index = 41;
char s1_random[s1_index];
s1(s1_random);
printf("\ns1 = ");
puts(s1_random);
printf("s2 = ");
int s2_index = 21;
char s2_input[s2_index];
s2(s2_input, s2_index);
if(s2_input[1] == '\0')
{
printf("Size too small");
exit(0);
}
if(s2_input[21] != '\0' )
{
printf("Size too big");
exit(0);
}
printf("ch = ");
int replacement = getchar();
if(replacement == EOF)
break;
while(getchar() != '\n');
printf("\n");
strfilter(s1_random, s2_input, replacement);
printf("\ns1 filtered = ");
puts(s1_random);
printf("Do you wish to run again? Yes(Y), No(N) ");
int run = getchar();
// or include ctype.h and do:
// run == EOF || toupper(run) == 'N'
if(run == EOF || run == 'N' || run == 'n')
break;
while(getchar() != '\n');
}
}
void s1(char *random)
{
int limit = 0;
char characters;
while((characters = (('A' + (rand() % 26))))) /* random generatro */
{
if(limit == 41)
{
*(random + 41 - 1) = '\0';
break;
}
*(random + limit) = characters;
limit++;
}
}
void s2(char *s2_input, int index)
{
char array[21] = "123456789012345678901"; /* populated array to make sure no random memory is made */
char input;
int count = 0;
int check = 0;
while((input = getchar() ))
{
if(input == '\n')
{
*(s2_input + count) = '\0';
break;
}
else if(input < 65 || input > 90)
{
printf("invalid input");
exit(0);
}
*(s2_input + count) = input;
count++;
}
index = count;
}
void strfilter(char *random, char *s2_input, char replacement) /* replacement function */
{
while(*s2_input)
{
char *temp = random;
while(*temp)
{
if(*temp == *s2_input)
*temp = replacement;
temp++;
}
s2_input++;
}
}
I tried a making a temporary pointer and replacing it with the array notation but I still would need to have the array notation somewhere. I can have the array defined somewhere but that's it. Any help would be greatly appreciated!
I just got clarification from the professor on what he wants.
You don't have to initialize s2 as an array you can initialize it as pointer to integer (int s2;) then you can do a pointer to an array (int (s1)[41];) then point to the single element of the array by doing this: s2 = s1; and incriminating to the next element by doing this: s2++
Does this make sense to anyone? I understand that he wants me to make a int pointer, and then use that to point to a certain element in the array however I am not sure on how to implement that.
I interpreted this as that you need to replace
*(random + limit) = characters;
with
*random++=characters;
and
*(s2_input + count) = input;
becomes
*s2_input++ = input;
i.e. he is asking you to move the pointer to the next point as you use it rather than recalculate each time.
Below are 3 ways of doing the same thing.
void s1(char *random)
{
for(int limit=0;limit<40;++limit)
{
char characters = 'A' + (rand() % 26);
// random[limit]=characters;
// *(random + limit) = characters;
*random++=characters;
}
// random[limit]='\0';
// *(random + limit) = '\0';
*random='\0';
}
A few issues ...
Hardwiring the limit in s1 is bad. Better to pass the max length as an arg.
The "Size too big" check in main must be done in s2 to prevent overflow/UB.
Here is the refactored code. I just fixed the pointer usage, but didn't test otherwise.
#include <stdio.h>
#include <stdlib.h>
/*Function Prototypes*/
int main();
#if 0
void s1(char *random);
#else
void s1(char *random,int maxlen);
#endif
#if 0
void s2(char *s2_input, int index);
#else
int s2(char *s2_input, int index);
#endif
void strfilter(char *random, char *s2_input, char replacement);
int
main()
{
for (;;) {
int s1_index = 41;
char s1_random[s1_index];
s1(s1_random,s1_index);
printf("\ns1 = ");
puts(s1_random);
printf("s2 = ");
int s2_index = 21;
char s2_input[s2_index];
#if 0
s2(s2_input, s2_index);
if (s2_input[1] == '\0') {
printf("Size too small");
exit(0);
}
#else
int len = s2(s2_input, s2_index);
if (len < 2) {
printf("Size too small\n");
exit(0);
}
#endif
// NOTE/BUG: the s2 function has to check this -- if too much data entered,
// s2 will overflow the buffer before we get here (causing UB)
#if 0
if (s2_input[21] != '\0') {
printf("Size too big");
exit(0);
}
#endif
printf("ch = ");
int replacement = getchar();
if (replacement == EOF)
break;
while (getchar() != '\n');
printf("\n");
strfilter(s1_random, s2_input, replacement);
printf("\ns1 filtered = ");
puts(s1_random);
printf("Do you wish to run again? Yes(Y), No(N) ");
int run = getchar();
// or include ctype.h and do:
// run == EOF || toupper(run) == 'N'
if (run == EOF || run == 'N' || run == 'n')
break;
while (getchar() != '\n');
}
}
void
s1(char *random,int maxlen)
{
#if 0
int limit = 0;
char characters;
/* random generatro */
while ((characters = (('A' + (rand() % 26))))) {
if (limit == 41) {
*(random + 41 - 1) = '\0';
break;
}
*(random + limit) = characters;
limit++;
}
#else
char characters;
/* random generatro */
for (--maxlen; maxlen > 0; --maxlen) {
characters = 'A' + (rand() % 26);
*random++ = characters;
}
*random = 0;
#endif
}
#if 0
void
s2(char *s2_input, int maxlen)
{
/* populated array to make sure no random memory is made */
char array[21] = "123456789012345678901";
char input;
int count = 0;
int check = 0;
while ((input = getchar())) {
if (input == '\n') {
*(s2_input + count) = '\0';
break;
}
else if (input < 65 || input > 90) {
printf("invalid input");
exit(1);
}
*(s2_input + count) = input;
count++;
}
index = count;
}
#else
int
s2(char *s2_input, int maxlen)
{
int input;
int count = 0;
--maxlen;
while ((input = getchar()) != EOF) {
if (input == '\n')
break;
if (input < 65 || input > 90) {
printf("invalid input\n");
exit(0);
}
if (maxlen <= 0) {
printf("input too long\n");
exit(1);
}
*s2_input++ = input;
--maxlen;
++count;
}
*s2_input = 0;
return count;
}
#endif
/* replacement function */
void
strfilter(char *random, char *s2_input, char replacement)
{
while (*s2_input) {
char *temp = random;
while (*temp) {
if (*temp == *s2_input)
*temp = replacement;
temp++;
}
s2_input++;
}
}
In the above code, I've used cpp conditionals to denote old vs. new code:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
Note: this can be cleaned up by running the file through unifdef -k

Anagram of a string using pointer arithmatic

Here is the code to find the anagram for a string. I am using pointer array to do it but want to do it using pointer arithmetic.
#include <stdio.h>
int check_anagram(char [], char []);
int main()
{
char a[100], b[100];
int flag;
printf("Enter first string\n");
gets(a);
printf("Enter second string\n");
gets(b);
flag = check_anagram(a, b);
if (flag == 1)
printf("\"%s\" and \"%s\" are anagrams.\n", a, b);
else
printf("\"%s\" and \"%s\" are not anagrams.\n", a, b);
return 0;
}
int check_anagram(char a[], char b[])
{
int first[26] = {0}, second[26] = {0}, c = 0;
while (a[c] != '\0')
{
first[a[c]-'a']++;
c++;
}
c = 0;
while (b[c] != '\0')
{
second[b[c]-'a']++;
c++;
}
for (c = 0; c < 26; c++)
{
if (first[c] != second[c])
return 0;
}
return 1;
}
--> How to using pointer arithmetic and find it.
In the while loop :
while (a[c] != '\0')
{
first[a[c]-'a']++;
c++;
}
--> Can we modify it to below way so that it will work
while(*(a+c)!='\0')
{
*(first *(a+c)-'a')++;
c++;
}
first[a[c]-'a']++ = first[*(a+c)-'a']++ = (*(first+(*(a+c)-'a')))++
The usual way to process an array using pointers is by initializing a pointer to the beginning of the array, and then increment it, rather than doing pointer arithmetic to index from the beginning each time.
char *c = a;
while (*c != 0) {
first[*c - 'a']++;
c++;
}
If you need to use pointer arithmetic for first as well, then it would be:
(*(first + *c - 'a'))++

Segmentation fault (Core Dumped)-- Structures and Pointers--C language

I have gotten my code to compile, but after running and entering input, the core dumps. I am aware this this must be from a pointer problem, but I am unaware of where the problem stems. The goal of the code is to take user input of a DNA sequence, then print out how many times each base was entered. Thank you in advance for your responses!
#include <stdio.h>
#include <string.h>
#define N 25
void countBase (char *dnaSequence, int n) //countBase function declaration
{
int i;
char *p;
struct
{
int aCount;
int cCount;
int tCount;
int gCount;
}dnaCount;
p = &dnaSequence[0];
for (p = 0; i < N; p++)
{
if (*p == 'A' || *p =='a')
{
dnaCount.aCount++;
}
if (*p == 'C' || *p == 'c')
{
dnaCount.cCount++;
}
if (*p == 'T' || *p == 't')
{
dnaCount.tCount++;
}
if (*p == 'G' || *p == 'g')
{
dnaCount.gCount++;
}
}
printf("Number of A's : %d\n", dnaCount.aCount);
printf("Number of C's : %d\n", dnaCount.cCount);
printf("Number of T's : %d\n", dnaCount.tCount);
printf("Number of G's : %d\n", dnaCount.gCount);
}
int main(int argc, char *argv[])
{
char dnaSequence [N];
printf("Enter a DNA sequence\n"); //prints prompt
fgets(dnaSequence, N, stdin); //retrieves user input
printf("Sequence: \n%s", dnaSequence); //prints entered sequence
countBase(dnaSequence, N); //function call
return 0; //terminating line
}
You have several issues going on there:
A runaway pointer - you do not increment i in the for loop (it turns out that you do not need i at all - read on)
You ignore n passed into the function, using N instead - you do not need to pass n either, but if you choose to do it, you should use it in the loop
Your counters are not initialized - you need to set counters to zero, or zero out the entire struct.
Here is how you can fix your code:
void countBase (char *p) {
struct {
int aCount;
int cCount;
int tCount;
int gCount;
} dnaCount = {0}; // Set all counters to zero
// Loop will end when you reach the end of null-terminated string
while (*p) {
if (*p == 'A' || *p =='a') {
dnaCount.aCount++;
} else if (*p == 'C' || *p == 'c') {
dnaCount.cCount++;
} else if (*p == 'T' || *p == 't') {
dnaCount.tCount++;
} else if (*p == 'G' || *p == 'g') {
dnaCount.gCount++;
}
p++;
}
printf("Number of A's : %d\n", dnaCount.aCount);
printf("Number of C's : %d\n", dnaCount.cCount);
printf("Number of T's : %d\n", dnaCount.tCount);
printf("Number of G's : %d\n", dnaCount.gCount);
}
You never initialized i , nor dnaCount. Change int i; to:
int i = 0;
and also zero-initialize your counters. Using uninitialized variables causes undefined behaviour.

convert a character value to integer value

here when ever i find 'h' i have to access the values between p and h i.e 123 and i want that has int and store it in value as 123 itself how can i do this can any one tell me the logic, that code that i have written is not working and how to copy the values when the pointer is getting incremented
main()
{
char *ptr1 = "p123h12";
int value;
while(*ptr1!= '\0')
{
if(*ptr1 == 'h')
{
value = (int)atoi(ptr1);
printf("%d\n", value);
}
ptr1++;
}
}
With sscanf:
int value;
sscanf (ptr1,"p%dh12",&value);
Update
int i,j;
int values[MAX_VALUES];
int startIdx = -1;
char *ptr1 = "p123hxxxxp124hxxxxp123145hxxxx";
char buffer[16];
for(i=0,j=0; i<strlen(ptr1);i++)
{
if(startIdx>=0 && ptr[i] == 'h')
{
strncpy(buffer,ptr1+startIdx,i-startIdx+1);
buffer[i-startIdx+1]='\0';
sscanf (buffer,"p%dh",&(values[j++]));
startIdx = -1;
}
else if(ptr[i] == 'p')
{
startIdx = i;
}
}
Here's a good possible starting point:
#include <stdio.h>
#include <ctype.h>
int main (void) {
char *p, *str = "p123h12p97h62p32h";
int accum = 0;
// Process every character.
for (p = str; *p != '\0'; p++) {
// 'p' resets the accumulator.
// 'h' outputs the accumulator.
// Any digit adjusts the accumulator.
if (*p == 'p') accum = 0;
if (*p == 'h') printf ("Processing %d\n", accum);
if (isdigit (*p)) accum = accum * 10 + *p - '0';
}
return 0;
}
This will work fine if your input string follows your specified format, outputting:
Processing 123
Processing 97
Processing 32
If there's the possibility that your input string is not so well formed, you'll need to add some defensive coding.

Resources