C : mark the every struct, union, array elements - c

I want to show how stack is allocated through pointers on struct, union, array
I just have no clue how to approach. The following is my try.
// to check the boundary
char *minimum_pointer, *maximum_pointer ;
// to check marked
void markmark(char *x, int size, char marking_address) {
minimum_pointer = x;
maximum_pointer = minimum_pointer + size;
// is this correct?
// I am trying to place marking_address
// to every byte of x
if (*minimum_pointer>marking_address || *maximum_pointer<marking_address) {
printf("%s \n", "out of boundary");
}
int number_of_array_element = size/sizeof(char);
for (int i=0; i<number_of_array_element; i++) {
if (&x[i] >= minimum_pointer && &x[i] <= maximum_pointer) {
x[i] = marking_address;
// am I doing this right?
// I need to place the address to every byte of input x
}
}
}
int main(int argc, const char * argv[]) {
struct structure_example {
char* a ;
char b[20] ;
float c ;
} str_ex;
markmark((char *) &str_ex, sizeof(str_ex), 0xa1);
union union_example {
float a ;
char b ;
int c ;
} uni_ex;
markmark((char *) &uni_ex, sizeof(uni_ex), 0xa2);
char arr_ex[50] ;
markmark((char *) &arr_ex, sizeof(arr_ex), 0xa3);
return 0;
}
My question is
maximum_pointer = minimum_pointer + size;
// is this correct?
// I am trying to place marking_address
// to every byte of x
And another question is
int number_of_array_element = size/sizeof(char);
for (int i=0; i<number_of_array_element; i++) {
if (&x[i] >= minimum_pointer && &x[i] <= maximum_pointer) {
x[i] = marking_address;
// am I doing this right?
// I need to place the address to every byte of input x
}
}
What is confusing me is that
how and what do I need to initialize the struct and union and array.
Thanks,

if you want the address of the stack then minimum_pointer = x is not correct, that would only make minimum_pointer point to the same thing x points to i.e.
char* p = "42";
markmark(p, ...
it doesn't say anything about the stack, you need to take the address of x instead
minimum_pointer = &x;
i think if you look in the standard header file stdarg.h you can get some hints how to work with the stack.

Related

How to access elements of array when parameter is double pointer?

First function changes big letter to small. In main I need to have five strings and with function konvertuj I have to go through that array and check for each letter if it's big and convert it to small. The point is that I don't know how to access each character of string in the function. (It's study example so it has to be done with these predefined functions.
char v2m(char z){
char m = z + 0x20;
return m;
}
void konvertuj(char **niz, int n){
for (int i = 0; i < n; i++)
if(*niz[i] > 'A' && *niz[i] < 'Z')
*niz[i] = v2m(*niz[i]);
}
int main(){
char **niz;
niz[0] = "Voda";
niz[1] = "KraISSa";
niz[2] = "somsssR";
niz[3] = "aaaaa";
niz[4] = "WeWeWeW";
for (int i = 0; i < 5; i++)
{
int d = -1;
while(niz[i][++d]);
konvertuj(&niz[i], d);
printf("%s ", niz[i]);
}
}
v2m - no need of the variable m
konvertuj no need to iterate through the same letters all over again. You want to convert 1 letter as you iterate in main. Your condition is wrong as you will ignore 'A' and 'Z'
Pointer to pointer does not have allocated space to accommodate 5 pointers. You need to allocate this space. In your code is it UB.
3.a You assign the pointers to the string literals. Attempt to modify the string literal invokes Undefined Behaviour. In my code, I use compound literals which are modifiable.
3.b use correct type for indexes (size_t).
char v2m(char z){
return z + 0x20;
}
void konvertuj(char *niz, size_t n){
if(niz[n] >= 'A' && niz[n] <= 'Z')
niz[n] = v2m(niz[n]);
}
int main(void){
char **niz = malloc(5 * sizeof((*niz)));
niz[0] = (char[]){"Voda"};
niz[1] = (char[]){"KraISSa"};
niz[2] = (char[]){"somsssR"};
niz[3] = (char[]){"aaaaa"};
niz[4] = (char[]){"WeWeWeW"};
for (size_t i = 0; i < 5; i++)
{
size_t d = 0;
while(niz[i][d])
konvertuj(niz[i], d++);
printf("%s ", niz[i]);
}
}
As I( understand you need to keep the function names types and parameters
Sure, it is possible to write it the way you did, but you have to build things accordingly and you did not.
And there some errors, anyway. I will try to show you some points. Please be patient.
niz[0] = "Voda";
niz[1] = "KraISSa";
niz[2] = "somsssR";
niz[3] = "aaaaa";
niz[4] = "WeWeWeW";
In C in general you can not just assign a value to a string. You use something like
strcpy( niz[0], "ANewValue");
v2m()
Instead of
char v2m(char z){
char m = z + 0x20;
return m;
}
You can just write
char v2m(char z) { return z + 0x20; }
There is no need to declare a char just for holding the return value.
IIUC you can not change the function prototypes...
konvertuj()
void konvertuj(char **niz, int n){
for (int i = 0; i < n; i++)
if(*niz[i] > 'A' && *niz[i] < 'Z')
*niz[i] = v2m(*niz[i]);
}
here I believe you missed the point that the function will receive just a string each time is called, not the whole vector of strings.
The int n is just the length of the string, and even if you could not use strlen() to compute it, it should probably be done inside the function.
but I believe you can not change this prototype also.
note that you are not including 'A' and 'Z' in your test. Maybe you should use '>=' and '<=' in the tests.
since the function gets a single string each call, you must remove many of the '*'
note that you had the strings declared as literals, CONSTANTS that you can not change. The first time you try to change a letter your program will abort
This one below should work and you can compare:
void konvertuj(char *niz, int n)
{
for (int i = 0; i < n; i++)
if(niz[i] >= 'A' && niz[i] <= 'Z')
niz[i] = v2m(niz[i]);
}
main()
Instead of
char **niz;
niz[0] = "Voda";
niz[1] = "KraISSa";
niz[2] = "somsssR";
niz[3] = "aaaaa";
niz[4] = "WeWeWeW";
You could write just
char niz[][15] =
{
"Voda",
"KraISSa",
"somsssR",
"aaaaa",
"WeWeWeW"
};
In C just the last dimension must be declared, e.g. the '15' above, since the compiler can determine here the other dimension. And this way you can initialize all of them directly. But in order to change one in the code you need to use a loop and replace letter by letter, or call
strcpy( niz[0], "ANewValue");
Also you can initialize just a few of them, and even out of order, as in
char niz[8][15] =
{
[2] = "somsssR",
[3] = "aaaaa",
[5] = "AomsssZ",
[6] = "A",
[0] = "Voda",
[1] = "KraISSa",
[4] = "WeWeWeW",
[7] = ""
};
and this is really handy.
Computing the number of strings
Note that you can compute the number of strings and even assign "TheLastValue" to the last one, by writing
int n = sizeof(niz)/sizeof(niz[0]); // total of strings
strcpy( niz[n-1], "TheLastValue"); // changes the last string
printf("Total of %llu values\n", sizeof(niz)/sizeof(niz[0]));
What if char** niz is needed?
This is a really common paradigm in C and C++, and it is very useful. You may recall that the prototype for main() is
int main( int argc, char** argc)
for every C program, so you can see how common it is.
Fact is that when you declare niz as char** you are declaring a single variable. What is niz? Well, it is a pointer to a pointer to a char.
niz is char**
*niz is char*
**niz is a single char
But niz is a pointer and it is pointing to nowhere when declared. In your case you want niz pointing to not one but FIVE strings. And if you do nothing the program will abort the first time you try to use it...
You need to build this:
A string is a pointer to the first char, char*
so niz needs to point to an area capable of holding 5 pointers to char
What about the size of a pointer to char? That is easy: sizeof(char*)
Then you need to make each niz[x] point to the required string.
It will not happen by itself. You must build each and every one.
An example: building char** sample from niz as declared above
The code below builds sample as an array of pointers, pointing to the same strings declared and allocated for niz[][] above, and them prints them all
// building an array of pointers to the strings in niz
char** sample = NULL; // ok, points to nothing
unsigned area = n * sizeof(char*); // n pointers to strings
sample = (char**) malloc(area);
for( int i=0; i<n; i+=1)
sample[i] = niz[i];
printf("\n=>\tPrinting the %d strings using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, sample[i]);
Note that the strings already exists and we are just pointing to them. A new reference only.
A new example: building char** copy as a full copy of niz
It is very very important to see the difference here: copy points to an array of pointers, but each pointer points to a copy of the corresponding string declared in niz and referenced in the sample array.
// building 'copy' as an array of pointers to the strings once in niz
char** copy = NULL; // ok, points to nothing
copy = (char**) malloc(area);
for( int i=0; i<n; i+=1)
{
copy[i] = (char*) malloc( (1 + sizeof(niz[i])) * sizeof(char) );
// large enough to hold it
int j = 0; // copy each letter
for ( ; niz[i][j] != 0; j+=1 ) copy[i][j] = niz[i][j];
copy[i][j] = 0; // this terminates the string
}
printf("\n=>\tPrinting the %d copies using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, copy[i]);
Note: it is in general not recommended to cast the pointers return by malloc() in C, as in the lines
copy = (char**) malloc(area);
// or
copy[i] = (char*) malloc( (1 + sizeof(niz[i])) * sizeof(char) );
I just do not care and prefer to write all them down explicitly, as a reminder to myself of what is what. Sure, in C++ you must declare this, but is is rare to allocate memory this way in C++ since C++11. Fell free to use whatever rule you see fit
A complete example
This is the output
PS C:\src\ifdef> gcc -o teste -Wall -Wextra -Wpedantic -std=c17 so210126.c
PS C:\src\ifdef> ./teste
Total of 8 values
Before: Voda (4)
After: voda
Before: KraISSa (7)
After: kraissa
Before: somsssR (7)
After: somsssr
Before: aaaaa (5)
After: aaaaa
Before: WeWeWeW (7)
After: wewewew
Before: AomsssZ (7)
After: aomsssz
Before: A (1)
After: a
Before: TheLastValue (12)
After: thelastvalue
=> Printing the 8 strings using the pointers
0: 'voda'
1: 'kraissa'
2: 'somsssr'
3: 'aaaaa'
4: 'wewewew'
5: 'aomsssz'
6: 'a'
7: 'thelastvalue'
=> Printing the 8 copies using the pointers
0: 'voda'
1: 'kraissa'
2: 'somsssr'
3: 'aaaaa'
4: 'wewewew'
5: 'aomsssz'
6: 'a'
7: 'thelastvalue'
PS C:\src\ifdef>
I compiled just on gcc 10.2 on Windows.
This is the example code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char v2m(char z) { return z + 0x20; }
void konvertuj(char *niz, int n)
{
for (int i = 0; i < n; i++)
if(niz[i] >= 'A' && niz[i] <= 'Z')
niz[i] = v2m(niz[i]);
}
int main(void)
{
char niz[8][15] =
{
[2] = "somsssR",
[3] = "aaaaa",
[5] = "AomsssZ",
[6] = "A",
[0] = "Voda",
[1] = "KraISSa",
[4] = "WeWeWeW",
[7] = ""
};
int n = sizeof(niz)/sizeof(niz[0]); // total of strings
strcpy( niz[n-1], "TheLastValue"); // changes the last string
printf("Total of %llu values\n", sizeof(niz)/sizeof(niz[0]));
for (int i = 0; i < n; i++)
{
int d = 0;
while ( niz[i][d] != 0) d+=1;
printf("Before: %s (%d)\n", niz[i], d);
konvertuj( niz[i], d );
printf("After: %s\n", niz[i]);
}
// building an array of pointers to the strings in niz
char** sample = NULL; // ok, points to nothing
unsigned area = n * sizeof(char*); // n pointers to strings
sample = (char**) malloc(area);
for( int i=0; i<n; i+=1)
sample[i] = niz[i];
printf("\n=>\tPrinting the %d strings using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, sample[i]);
// building 'copy' as an array of pointers to the strings once in niz
char** copy = NULL; // ok, points to nothing
copy = (char**) malloc(area);
for( int i=0; i<n; i+=1)
{
copy[i] = (char*) malloc( (1 + sizeof(niz[i])) * sizeof(char) ); // large enough to hold it
int j = 0; // copy each letter
for ( ; niz[i][j] != 0; j+=1 ) copy[i][j] = niz[i][j];
copy[i][j] = 0; // this terminates the string
}
printf("\n=>\tPrinting the %d copies using the pointers\n", n );
for( int i=0; i<n; i+=1)
printf("%2d: '%s'\n", i, copy[i]);
for( int i=0; i<n; i+=1) free(copy[i]); // destroy each string
free(copy); // destroy the array;
free(sample); // sample points to static memory...
return 0;
}
As for the very very long post: I wanted to leave an example of the
solution plus an example of the steps involved in order to build a char** vector from
existing strings and as an independend copy.

C - pointing members of array of struct into another array ( no duplicate struct data just point to it )

I have two identical arrays of struct , one in reverse order.
The problem is that i don't want duplicate the same data into the two arrays , i would a reversed array with elements pointing elements of the first array in a way that i can edit the members of struct of first array or from the reversed array taking effect in both.
you can view the source and run it online here https://onlinegdb.com/SJbepdWxS
#include <stdio.h>
typedef struct point{
int id;
float x,y,z;
} point;
void printPoints(point *pts,int len){
int i = 0;
while (pts !=NULL && i < len){
printf("id %d x %f y%f z %f\n",pts->id,pts->x,pts->y,pts->z);
pts++;
i++;
}
}
void translatePoints(point *pts,int len,float t){
int i = 0;
while (pts !=NULL && i < len){
pts->x = pts->x + t;
pts->y = pts->y + t;
pts->z = pts->z + t;
pts++;
i++;
}
}
void reversePoints(point *pts, int len, point *rev){
int i = 0;
int j = len;
while (i < len){
j=len-i-1;
rev[j]=pts[i];
i++;
}
}
int main()
{
int i;
int t1=200;
int t2=300;
int len=3;
point points[len];
point rev_points[len];
for(i=0; i<len ; i++){
points[i].id=i;
points[i].x=10+i;
points[i].y=20+i;
points[i].z=30+i;
}
//point * pts = points;
printf("\nprint points \n\n");
printPoints(points,len);
printf("\ntranslate points %d...\n\n",t1);
translatePoints(points,len,t1);
printf("\nprint points\n\n");
printf("\nreverse points to rev_points\n");
reversePoints(points,len,rev_points);
printf("\nprint rev_points \n\n");
printPoints(rev_points,len);
printf("\ntranslate rev_points %d...\n\n",t2);
translatePoints(rev_points,len,t2);
printf("\nprint rev_points\n\n");
printPoints(rev_points,len);
printf("\nprint points\n\n");
printPoints(points,len);
return 0;
}
I expect that struct values of both arrays change when i change value in one of the two array.
But changing values of struct in the first array , the second array not changes and the other way around.
One way to look at this is a set of points and two permutations on the set. This sets up a points array, which is used as a set, and forward_points and reverse_points as arrays of pointers to the point array that we are going to use as permutations.
#include <stdio.h>
struct Point {
int id;
float x,y,z;
};
/* Print a point. */
static void printPoint(struct Point *point) {
printf("id %d x %f y%f z %f\n",point->id,point->x,point->y,point->z);
}
/* These print out an array of pointers to point. */
static void printPointsRef(struct Point **ref, int len) {
struct Point **end = ref + len;
while(ref < end) printPoint(*(ref++));
}
/* This translates all the `pts` up to `len` by `(1,1,1)*t`. */
static void translatePoints(struct Point *pts, int len, float t) {
struct Point *end = pts + len;
while(pts < end) {
pts->x = pts->x + t;
pts->y = pts->y + t;
pts->z = pts->z + t;
pts++;
}
}
/* Helper function to `main`. */
static void printPoints(struct Point **forward_points,
struct Point **reverse_points, int len) {
printf("print points\nprint points forward:\n");
printPointsRef(forward_points,len);
printf("print points reverse:\n");
printPointsRef(reverse_points,len);
printf("\n");
}
int main(void)
{
const int len = 3;
/* This is the actual points structure. */
struct Point points[len];
/* These are arrays of pointers to points; they are
permutations of `points`. */
struct Point *forward_points[len], *reverse_points[len];
int i;
const int t1=200;
for(i=0; i<len; i++) {
/* Initialise element `i` of `points`. */
points[i].id=i;
points[i].x=10+i;
points[i].y=20+i;
points[i].z=30+i;
/* Initialise element `i` of `forward_points`
to point to `points[i]`, and `backward_points`
to point the other way (it doesn't matter that
the backwards points are uninitialised, they
will be.) */
forward_points[i] = &points[i];
reverse_points[i] = &points[len - 1 - i];
}
printPoints(forward_points, reverse_points, len);
/* Translation is a vector space operation and doesn't
care about order; we just do it on the original points. */
printf("translate points %d...\n\n",t1);
translatePoints(points,len,t1);
printPoints(forward_points, reverse_points, len);
return 0;
}
Of course, there is no integrity constraints on the pointers; nothing stopping one from pointing at anything, null, the same elements, or anything else.
I added an other struct with one element that is a pointer
typedef struct ptr_point{
point * p;
} ptr_point;
I edited the function reversePoints
void reversePoints(point *pts, int len, ptr_point *rev){
// This function is used only to test pointers
int i = 0;
int j = len;
while (i < len){
j=len-i-1;
rev[j].p = &pts[i];
i++;
}
}
and added another function to print ptr_points
void printPtrPoints(ptr_point *pts,int len){
int i = 0;
while (i < len){
printf("id %d x %f y%f z %f\n",pts->p->id,pts->p->x,pts->p->y,pts->p->z);
pts++;
i++;
}
}
and declaring the second array as ptr_point array
ptr_point rev_points[len];
In conclusion : now data in the second array are not replicated but pointing to element structure of the first array.
The need to not replicate data arise in presence of millions of coordinate points that if replicate more than one time , sorting it for example by x, y, z and so on , occupe much memory with the difficulty of managing .
This fix however forces me to use structures->type in order to change the access mode to read or set values.
I don't know if this is the best solution but it has solved the problem for not duplicate the data.
you can run the source with fixes here: https://onlinegdb.com/SknP_i-eS
Thank you all for the advice.

How do I use pointers correctly in my code?

Hello everyone I just started learning how to use pointers and I got stuck in my code. I need to write a code that modifies(corrects the uppercases and lowercases and finds out the year of every citizen) and sorts a list of citizens. For an example if the user entry is:
4 //just the number of citizens
lAna lanIc 1999
lana lanac 1999
laNa LaneC 1989
lAna lanOc 1999
the display must be :
18; Lanac, Lana
18; Lanic, Lana
18; Lanoc, Lana
28; Lanec, Lana
#include <stdio.h>
#include <string.h>
#include <ctype.h>
typedef struct {
char name[26];
char surname[26];
int birth;
} citizen; //the structer for the citizen
void modify(citizen *g);
int compare(citizen g1, citizen g2); //compares citizens by birth or surname or name
void sort(citizen g[], int); //insertion sort
int main()
{
int n, i;
citizen g[100];
scanf("%d", &n);
for(i = 0; i < n; i++) {
scanf("%s %s %d", g[i].name, g[i].surname, &g[i].birth);
modify(g + i);
}
sort(g, n);
for (i = 0; i < n; i++) {
printf("%2d; %s %s\n", g[i].birth, g[i].surname, g[i].name);
}
return 0;
}
void modify(citizen *g) { //here I'm having trouble
int i = 0;
//trying to correct the name
if(isalpha(*g[i].name[0])) {
*g[i].name[0] = toupper(*g[i].name[0]);
}
for(i = 1; i < strlen(*g[i].name); i++) {
*g[i].name = toupper(*g[i].name);
}
//then the surname
if(isalpha(*g[i].surname[0])) {
*g[i].surnma[0] = toupper(*g[i].surname[0]);
}
for(i = 1; i < strlen(*g[i].surname); i++) {
*g[i].surname = toupper(*g[i].surname);
}
*g[i].birth = 2017 - *g[i].birth; //finding how old is the citizen
}
int compare(citizen g1, citizen g2) {
if(g1.birth == g2.birth) {
if(!strcmp(g1.surname, g2.surname)) {
return strcmp(g1.name,g2.name);
}
else {
return strcmp(g1.surname, g2.surname);
}
}
else if (g1.birth > g2.birth) {
return 1;
}
return -1;
}
void sort(citizen g[], int n) { //insertion sort
int i, j;
citizen tmp;
for(i = 0; i < n; i++) {
tmp = g[i];
j = i;
while(j > 0 && compare(g[j-1], tmp)) {
g[j] = g[j - 1];
j--;
}
g[j] = tmp;
}
}
The basics:
In your main function this:
citizen g[100];
declares an array of 100 citizens. g is an array which is not a pointer.
In your modify function
modify(citizen *g)
g is a pointer to a citizen. It is not an array. So you're probably asking why it is legal to do this:
modify(g + i);
The reason is that, in the context of using g in an expression, it is transformed by the compiler into a pointer to its first element. We say "g decays to a pointer to its first element".
There are two ways to access the thing(s) that a pointer points to (we say "dereference the pointer"). The first is to use the * operator. If p is int* we can do
int x = *p;
If p points to an int that is in an array of ints, we can do pointer arithmetic. So we could do
int y = *(p + 3);
int z = *(p - 2);
If p points to the third element of an array that is at least size 6, y now has the same value as the sixth element and z has the same value as the first element.
The second way to dereference a pointer is to use subscript syntax. The syntax p[i] is exactly equivalent to *(p + i) and I mean exactly. Addition is commutative so p + i == i + p which means *(p + i) == *(i + p) which means (and this is legal in C) p[i] == i[p] Anyway each of the statements above can be written using subscripts
int x = p[0];
int y = p[3];
int z = p[-2];
Except to save our sanity, we tend to only use subscript syntax if p is a pointer to the first element of an array or the first element of a malloc'd block.
If p is a pointer to a struct (like your citizen struct, you can access the fields in the struct by dereferencing p and using the normal diot syntax.
int myBirth = (*p).birth;
The parentheses are necessary because the dot operator normally has higher precedence than the * operator. With *p.birth the C compiler thinks that p s a struct with a field called birth which it tries to dereference as a pointer. C provides a shortcut syntax for the (*p).birth thing which is
int myBirth = p->birth; // Exactly equivalent to (*).birth
Finally in C, you can obtain a pointer to an arbitrary object with the & operator.
int x = 0;
int* p = &x; // p is a pointer to x.
So when we say g decays to a pointer to its first element, what we mean is that the compiler transforms
modify(g + i);
to
modify(&g[0] + i);
So, you see, your modify function receives a pointer to an element of g. Looking at the first couple of lines of the function:
if(isalpha(*g[i].name[0])) {
*g[i].name[0] = toupper(*g[i].name[0]);
}
Because i is 0 at this point, `g[i].name` is the same as `(*g).name` or `g->name`. Use the last one for clarity. The `name` field is an array of chars, so `name[0]` is the first character of the name, which is what you want. You have an extra dereference with the leading * that you don't need. The above should be
if (isalpha(g->name[0])) {
g->name[0] = toupper(g->name[0]);
}
Except toupper does the isalpha check for you, so all that becomes
g->name[0] = toupper(g->name[0]);
I'll leave it to you to fix the rest of the function, except to mention the rather bad bug here:
for(i = 1; i < strlen(*g[i].surname); i++) {
*g[i].surname = toupper(*g[i].surname);
}
This actually makes no sense to me at all.
Instead of dereference pointer your way, I will give you answer here:
void modify(citizen *g) { //here I'm having trouble
int i = 0;
//trying to correct the name
//Is this really necessary?
if (isalpha(g->name[0])) {
g->name[0] = toupper(g->name[0]);
}
for (i = 1; i < strlen(g->name); i++) {
g->name[i] = toupper(g->name[i]);
}
//then the surname
//Is this really necessary?
if (isalpha(g->surname[0])) {
g->surname[0] = toupper(g->surname[0]);
}
for (i = 1; i < strlen(g->surname); i++) {
g->surname[i] = toupper(g->surname[i]);
}
g->birth = 2017 - g->birth; //finding how old is the citizen
}
I've also modify you compare function:
int compare(citizen *g1, citizen *g2) {
if (g1->birth == g2->birth) {
int resp = strcmp(g1->surname, g2->surname);
if (!resp) {
return strcmp(g1->name, g2->name);
}
return resp;
} else if (g1->birth > g2->birth) {
return 1;
}
return -1;
}

How to increment a variable when strstr finds the specified string

I'm wanting to have my variable houseTot increment by one every time strstr finds a string with "house" in it. I've essentially done this in my code:
struct Owner1_def
{
int totProps;
char type[40];
float monthlyPrice;
float maintenance;
int bedrooms;
int bathrooms;
};
typedef struct Owner1_def Owner1;
int main(void)
{
char *ptr;
int i = 0;
ptr = strstr(database[i].hometype, "house");
for(i = 0; i <= 3; ++i)
{
if (ptr != NULL)
houseTot++;
}
return 0;
}
But when the program prints houseTot's value, it's still at it's initialized value 0. I don't know much about strstr, but from what I've read, this should work.
The call to strstr() should be moved inside the loop so that the value stored in database[i].hometype can be checked on each iteration:
for(i = 0; i <= 3; ++i) {
ptr = strstr(database[i].hometype, "house");
if (ptr != NULL)
houseTot++;
}
Note that posted code has no definition for the array of structs database[], and the struct provided has no hometype field.

How to set a pointer to struct to NULL in C?

I have an array of pointer to struct, and for any reasons when I print this array, there is a spare element at the end of it, and thus causes the code to print a NULL byte at the end.
Is there anyway I can delete the last chunk of memory?
For example:
typedef struct
{
char *name;
} B;
typedef struct
{
B *var;
} A;
int main() {
int num = 5; //for example
A *foo = malloc(sizeof(A));
B *bar = malloc(num * sizeof(B));
for (int i = 0; i < num; i++) {
bar[i] = *create_b(&bar[i]); // some function that works.
}
foo->var = bar;
while (foo->var != NULL) {
printf("This is %s\n",foo->var->name);
foo->var++;
}
}
Everything is printed out just fine, but there's an unwanted printing at the end of the loop. Something like:
This is A
This is B
This is C
This is D
This is F
This is
Apparently the array only has 5 elements, the last one prints nothing.
Your printing loop is:
foo->var = bar;
while (foo->var != NULL) {
printf("This is %s\n",foo->var->name);
foo->var++;
}
But foo->var will never equal NULL, since you're just incrementing a pointer, so you will eventually read past the end of the bar array and your application will probably crash.
If you replace the while loop with for (int i = 0; i < num; i++), it will print the correct number of elements.
You can't do foo->var++, because there is no place in the array that is set to NULL. Also, using that ++ changes foo->var so after the loop foo->var no longer points at the start of the array, and you can not access the array again.
You need to allocate memory for some end-of-array marker, just like strings has the character \0 to mark the end of the string.
Try the following:
int main() {
int num = 5; //for example
A *foo = malloc(sizeof(A));
B *bar = malloc((num + 1) * sizeof(B)); // +1 for array terminator
for (int i = 0; i < num; i++) {
bar[i] = *create_b(&bar[i]); // some function that works.
}
bar[i].name = NULL; // Use this as a marker to mean end of array
foo->var = bar;
for (B *tmp = foo->var; tmp->name != NULL; tmp++) {
printf("This is %s\n",tmp->name);
}
}
Edit Had some errors in the code.
Your problem is probably in the function create_b, which you did not post.
Edit: no, that's probably wrong, sorry.
But surely this isn't what you want:
bar[i] = *create_b(&bar[i]);
You both pass in the address of bar[i] and set it equal to whatever the return value points to?

Resources