#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <ctype.h>
struct ALUMNO{
int cod;
char nombre[20], grupo[3], app[20], apm[20];
float prom,cali[5];
} al[20]={'\0'};
void gotoxy(int x,int y){
HANDLE hcon;
hcon = GetStdHandle(STD_OUTPUT_HANDLE);
COORD dwPos;
dwPos.X = x;
dwPos.Y= y;
SetConsoleCursorPosition(hcon,dwPos);
}
int main()
{
char gru[3];
int x = 0, sw, ac;
al[0].cod=12345;
strcpy(al[0].grupo,"1A");
strcpy(al[0].nombre,"Erick");
strcpy(al[0].app,"Medina");
strcpy(al[0].apm,"Ramirez");
al[0].prom=0.0;
al[1].cod=12346;
strcpy(al[1].grupo,"1A");
strcpy(al[1].nombre,"Emmanuel");
strcpy(al[1].app,"Sauceda");
strcpy(al[1].apm,"Perez");
al[1].prom=0.0;
al[2].cod=12347;
strcpy(al[2].grupo,"1B");
strcpy(al[2].nombre,"Vincio");
strcpy(al[2].app,"Lopez");
strcpy(al[2].apm,"Martinez");
al[2].prom=0.0;
//salon B
al[3].cod=12348;
strcpy(al[3].grupo,"1B");
strcpy(al[3].nombre,"Bryan");
strcpy(al[3].app,"Osuna");
strcpy(al[3].apm,"Beltran");
al[3].prom=0.0;
al[4].cod=12349;
strcpy(al[4].grupo,"1C");
strcpy(al[4].nombre,"Fullano");
strcpy(al[4].app,"Mangano");
strcpy(al[4].apm,"Centenario");
al[4].prom=0.0;
al[5].cod=12350;
strcpy(al[5].grupo,"1C");
strcpy(al[5].nombre,"Chapo");
strcpy(al[5].app,"Guzman");
strcpy(al[5].apm,"Loera");
al[5].prom=0.0;
//done
printf("Grupo: ");
scanf("%s",&gru);
gru[1]=toupper(gru[1]);
system("cls");
printf("Codigo\tAp.paterno\tap.materno\tnombre\tpromedio");
for (x=0, sw=0; x<25 && al[x].cod!=0; x++){
if (strcmp(gru,al[x].grupo)==0){
sw=1;
ac++;
}
if (sw==1){
gotoxy(1,ac);
printf("%i",al[x].cod);
gotoxy(12,ac);
printf("%s",al[x].app);
gotoxy(30,ac);
printf("%s",al[x].apm);
gotoxy(50,ac);
printf("%s",al[x].nombre);
gotoxy(60,ac);
printf("%.2f",al[x].prom);
}
}
ac=0;
}
For some reason, when you type in the correct group and hit enter, it will print maternal last names on top of others. Or some names maybe missing, or it's just my compiler. It works fine when you only have one name per group.
Your gru variable is used wrong in scanf. Should be gru, not &gru.
By the way, don't use scanf, use fgets
Related
What am I doing wrong? My code keeps in loop and n goes minus. It was supposed to return 0; at 0.Also whatever I do it starts with 3-2-1-0 even I type "2" it still keeps doing it 3-2-1-0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
static const char PSWRD[]="1234";
char p[6];
int n=3, y;
printf("Hos geldiniz");
do{
printf("\n\nOgrenci_ID:Elif");
fflush(stdout);
printf("\nSifre:");
scanf("%s", &p);
fflush(stdout);
y=strcmp(p, PSWRD);
if(y==0){
printf("\nGiris Basarili"); `//succesfull login`
return 0;
}else {
printf("Yanlis Sifre, tekrar deneyiniz", 3-n); //wrong password try again
printf("\nKalan hakkiniz ");
printf("%d\n", n);
getchar();
n--;}
if(n<1){
printf("\nHesabiniz bloke oldu");
return 0;
// that means you use all your chance and now you're blocked but my code aint stop here and n goes minus
}
// I am not exactly sure about "3"
//Also what ever i do it starts with 3-2-1-0 even i type "2" it's still keep doing it 3-2-1-0
}while (n<=3);
return 0;
}
while (n<=3);
doesn't agree with
n--;
You seem to want
while (n>0);
Its working for me!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
static const char PSWRD[]="1234";
char p[6];
int n=3, y;
printf("Welcome");
do{
printf("\n\nStudent_ID:Elif");
fflush(stdout);
printf("\nPassword:");
scanf("%s", p);
fflush(stdout);
y=strcmp(p, PSWRD);
if(y==0){
printf("\nSucessfull Login\n"); //succesfull login
return 0;
}else{
n--;
printf("\nWrong password, try again: "); //wrong password try again
printf("\nRemaining attempts ");
printf("%d\n", n);
getchar();
}
if(n<1){
printf("\nYour account has been blocked\n");
return 0;
}
}while (n>0);
}
When user introduces wrong password, you have more 2 tries and if you enter the password wrong on thats 2 tries program ends! But if you insert it right program makes login, so works fine
In your code, there is no increment of 'n', so the loop keeps going (because n is always smaller than 3). I'm not too sure of what you're trying to do, but you need to change your 'while' condition or statements of 'n' inside the loop.
Currently the loop keeps running forever:
When n=3 - > 3<=3 is true.
When n=2 - > 2<=3 is true.
Etc.
The only way it's going to end is when n decrements until it is equal to the absolute minimum value of an integer which is -2,147,483,648, then it will decrement one more time and change to 2,147,483,647 and the loop will end.
Use printf to watch the value of n, and you will quickly observe that your condition for the do...while loop is incorrect.
However, note the conditional, if(n<=0) with return.
Provide a minimal reproducible example, such as below...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int login(char* PSWRD)
{
int n=3, y;
char p[100+20];
printf("Hos geldiniz");
do{
printf("\nSifre:");
scanf("%100s", p); // limit input size, use p, not &p
if( 0 == strcmp(p, PSWRD) ) {
printf("\nsuccess!");
return 0;
}
printf("Yanlis Sifre, tekrar deneyiniz"); //wrong password try again
n--;
if(n<=0)
{
printf("\nHesabiniz bloke oldu");
return -1;
}
printf("n=%d\n",n); // print current n
} while (n<=3); // this should be (n>0)
return -1;
}
int main()
{
char* PASSWD = "password";
int result;
if( 0 > login(PASSWD) ) {
printf("\nfailed!\n");
exit(1);
}
printf("\nsuccess!\n");
// continue processing here
}
Caveat: Make sure you limit input size to avoid buffer overflow
Read no more than size of string with scanf()
I'm trying to write some code which would allow to render 3D graphics in console using characters and escape sequences (for color). I need it for one specific program I want to write, but, if possible, I would like to make it more universal. I'm experiencing something like screen tearing and I want to get rid of it (that the whole screen would be printed "at once"). The test is simply displaying screen filled with spaces with wite and black background (one full white frame then one full black one) in one second interval.
I have tried:
At the begging I thought about line buffering on stdout. Tried both disabling it and creating full buffor with size sufficient enough to hold every char on the screen. Second option provides better results, and by that I mean that less frames are teared, but they still are.
I thought it might be a problem with my terminal emulator (this question gave me the idea) so I started to mess around with other ones. I've got best result with Kitty but it's not there yet.
The next thing was to mess with Kitty configuration. I've noticed that if I would increase the input_delay setting to about 20 ms the problem would be almost gone. Just few of, and not every frame would be teared.
So, I came into the conclusion that in fact terminal emulators (or at least kitty) are being too fast and there might be some sort of race condition here, where buffer is not flushed yet fully and TE display both what was partially flushed and is part of old frame. Am I wrong? If not is there any way I can enforce terminals to wait for input to finnish before displaying it, or at least enforce input delay in C?
here is the relevant part of the code:
main.c
#include "TermCTRL/termCTRL.h"
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
int main()
{
termcell_t cell;
int k;
uint16_t x,y;
termCTRL_get_term_size(&x, &y);
sleep(1);
termCTRL_init();
uint8_t a = 0;
for(k=0; k<200; k++)
{
a^=255;
cell.bg.B = a;
cell.bg.G = a;
cell.bg.R = a;
cell.fg.B = a;
cell.fg.G = a;
cell.fg.R = a;
cell.symbol[0] = ' '; //symbol is in fact a string, because I want to use UTF chars too
cell.symbol[1] = '\0';
for(int xd=0; xd<x; xd++)
for(int yd=0; yd<y; yd++)
{
termCTRL_load_termcell(xd, yd, &cell);
}
termCTRL_update_screen();
sleep(1);
}
termCTRL_close();
return 0;
}
termCTRL.h
#pragma once
#include <stdint.h>
#define INPLACE_TERMCELL(FG_R, FG_G, FG_B, BG_R, BG_G, BG_B, SYMBOL) \
(termcell_t) { {FG_R, FG_G, FG_B}, {BG_R, BG_G, BG_B}, SYMBOL }
#define termCTRL_black_fill_screen() \
termCTRL_fill_screen(&INPLACE_TERMCELL(0, 0, 0, 0, 0, 0, " "))
typedef struct termcell_color_t
{
uint16_t R;
uint16_t G;
uint16_t B;
} termcell_color_t;
typedef struct termcell_t
{
termcell_color_t fg;
termcell_color_t bg;
char symbol[4];
} termcell_t;
typedef enum termCTRL_ERRNO
{
termCTRL_OUT_OF_BORDER = -2,
termCTRL_INVALID_TERMCELL = -1,
termCTRL_INTERNAL_ERROR = 0,
termCTRL_OK = 1,
} termCTRL_ERRNO;
void termCTRL_init();
void termCTRL_close();
void termCTRL_get_term_size(uint16_t *col, uint16_t *row);
termCTRL_ERRNO termCTRL_load_termcell(uint16_t x, uint16_t y, termcell_t *in);
void termCTRL_update_screen();
termCTRL_ERRNO termCTRL_fill_screen(termcell_t *cell);
termCTRL.c
#include "termCTRL.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define CONVERTED_TERMCELL_SIZE 44
#define CAST_SCREEN_TO_BUFFER \
char (*screen_buffer)[term_xsize][term_ysize][CONVERTED_TERMCELL_SIZE]; \
screen_buffer = _screen_buffer
static void *_screen_buffer = NULL;
static uint16_t term_xsize, term_ysize;
static char *IO_buff = NULL;
void termCTRL_get_term_size(uint16_t *col, uint16_t *row)
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
*col = w.ws_col;
*row = w.ws_row;
}
void int_decompose(uint8_t in, char *out)
{
uint8_t x = in/100;
out[0] = x + '0';
in -= x*100;
x = in/10;
out[1] = x + '0';
in -= x*10;
out[2] = in + '0';
}
termCTRL_ERRNO termCTRL_move_cursor(uint16_t x, uint16_t y)
{
char mov_str[] = "\x1b[000;000H";
if(x<term_xsize && y<term_ysize)
{
int_decompose(y, &mov_str[2]);
int_decompose(x, &mov_str[6]);
if(fputs(mov_str, stdout) == EOF) return termCTRL_INTERNAL_ERROR;
else return termCTRL_OK;
}
else
{
return termCTRL_OUT_OF_BORDER;
}
}
termCTRL_ERRNO termCTRL_load_termcell(uint16_t x, uint16_t y, termcell_t *in)
{
CAST_SCREEN_TO_BUFFER;
if(in == NULL) return termCTRL_INVALID_TERMCELL;
if(x >= term_xsize || y >= term_ysize) return termCTRL_OUT_OF_BORDER;
//because screen buffer was initialized, it is only needed to replace RGB values and symbol.
//whole escape sequence is already there
int_decompose(in->fg.R, &(*screen_buffer)[x][y][7]);
int_decompose(in->fg.G, &(*screen_buffer)[x][y][11]);
int_decompose(in->fg.B, &(*screen_buffer)[x][y][15]);
int_decompose(in->bg.R, &(*screen_buffer)[x][y][26]);
int_decompose(in->bg.G, &(*screen_buffer)[x][y][30]);
int_decompose(in->bg.B, &(*screen_buffer)[x][y][34]);
strcpy(&(*screen_buffer)[x][y][38], in->symbol); //copy symbol, note that it could be UTF char
return termCTRL_OK;
}
termCTRL_ERRNO termCTRL_fill_screen(termcell_t *cell)
{
uint16_t x, y;
termCTRL_ERRNO ret;
for(y=0; y<term_ysize; y++)
for(x=0; x<term_xsize; x++)
{
ret = termCTRL_load_termcell(x, y, cell);
if(ret != termCTRL_OK)
return ret;
}
return ret;
}
void termCTRL_update_screen()
{
uint16_t x, y;
CAST_SCREEN_TO_BUFFER;
termCTRL_move_cursor(0, 0);
for(y=0; y<term_ysize-1; y++)
{
for(x=0; x<term_xsize; x++)
fputs((*screen_buffer)[x][y], stdout);
fputs("\n", stdout);
}
//last line got special treatment because it can't have \n
for(x=0; x<term_xsize; x++)
fputs((*screen_buffer)[x][y], stdout);
fflush(stdout);
}
void termCTRL_init()
{
uint16_t x, y;
termCTRL_get_term_size(&term_xsize, &term_ysize);
IO_buff = calloc(term_xsize*term_ysize, CONVERTED_TERMCELL_SIZE);
setvbuf(stdout, IO_buff, _IOFBF, term_xsize*term_ysize*CONVERTED_TERMCELL_SIZE);
_screen_buffer = calloc(term_xsize*term_ysize, CONVERTED_TERMCELL_SIZE);
fputs("\e[?25l", stdout); //hide cursor
fputs("\x1b[2J", stdout); //clear screen
CAST_SCREEN_TO_BUFFER;
for(y=0; y<term_ysize; y++)
for (x=0; x<term_xsize; x++)
sprintf( (*screen_buffer)[x][y], "\x1b[38;2;200;200;000m\x1b[48;2;000;000;000m ");
termCTRL_update_screen();
}
void termCTRL_close()
{
free(_screen_buffer);
setvbuf(stdout, NULL, _IONBF, 0);
free(IO_buff);
printf("\e[?25h"); //show cursor
printf("\x1b[m"); //reset colors
printf("\x1b[2J"); //clear screen
}
I have the void function void isVaraRegistered that should check for existent numbers in the array that are introduced as varanummer in regVaror. If the introduced number already exists it should break from the regVaror function. I am not sure how to do it. How to set isVaraRegistered to true or false or any combination in fact. Please help!
//lager program lab
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define DEPOSIT 10
#define WORDLENGTH 30
#define MAX 10
struct varor{
int varunummer;
char namn[WORDLENGTH];
int lagersaldo;
};
typedef struct varor Vara;
Vara createVara(int varunummer, char namn[], int lagersaldo){
Vara v;
v.varunummer=varunummer;
strcpy(v.namn, namn);
v.lagersaldo=lagersaldo;
return v;
}
void isVaraRegistered(Vara reg[], int varunummer){
for(int n=0; n<MAX; n++){
if(reg[n].varunummer==varunummer) {
printf("\nError! Varunummer finns redan!\n\n");
}
break;
}
}
void regVaror( Vara reg[], int *pNrOfVaror){
char confirm;
char namn[WORDLENGTH],
tmp[WORDLENGTH];
int varunummer, lagersaldo;
printf("\nÄr du säkert att du vill registrera nya varor?\n1: Ja - (fortsätt)\n2: Nej - (gå tillbaka till menyn)\n");
scanf(" %c%*c", &confirm);// %*c för att inte skippa raden dvs skipppa ange varunummer
switch(confirm){
case '1':
do{
printf("Ange varunummer:");
gets(tmp);
varunummer=atoi(tmp);
isVaraRegistered(reg,varunummer);
printf("Ange namn:");
gets(namn);
printf("Ange lagersaldo:");
gets(tmp);
lagersaldo=atoi(tmp);
reg[*pNrOfVaror]=createVara(varunummer,namn,lagersaldo);
(*pNrOfVaror)++;
printf("\nRegristrera mer varor?\n1: Ja - (fortsätt)\n2: Nej - (gå tillbaka till menyn)\n");
scanf(" %c%*c", &confirm);
}while(confirm=='1');
case '2': break;
}
}
int main(){
int run=1;
Vara vRegister[MAX];
int nrOfVaror=0;
while(run){
char choice;
printf("\n\t\tMeny - Lager Program\n\n\
(1) Regristrera nya varor\n\b\b\b\b\
(2) Skriva ut alla varor\n\
(3) Söka efter varor\n\
(4) Ändra lagersaldot för varor\n\
(5) Sortera varor\n\
(6) Avregristrera varor\n\
(7) Avsluta programmet\n");
scanf(" %c%*c", &choice);
if(choice=='1') regVaror(vRegister, &nrOfVaror);
else if(choice=='7') run=0;
}
return 0;
}
A straight return will do it, but I tend to lean towards a more controlled exit in exceptional situations and let the function run through. Obviously there are scenarios where it's fine to have multiple returns but I try to keep it to a guard at the beginning and maybe a couple of special circumstances prior to finishing. But I wouldn't return from inside a loop. Just makes me feel dirty :)
So in your situation I would actually break as you are doing already which will return anyway... Your code is fine. But I'd lean towards this approach:
void isVaraRegistered(Vara reg[], int varunummer){
int found = 0;
for(int n=0; found == 0 && n<MAX; n++){
if(reg[n].varunummer==varunummer) {
printf("\nError! Varunummer finns redan!\n\n");//existing error msg
found++;
}
}
}
Note that this is just a personal coding style thing. Moving over to C# a few years ago thee was a push in our company to standardise and write a certain way and this sort of controlled execution of letting the full function run through was preferred.
--- Edit:
I was responding to the original code, you've updated since I started responding.
Incidentally, should should set int as your return type and return 1 or 0 indicating yes or no given the name of the function and return the found variable I introduced. Then where the function is called respond accordingly....and take out the printf as the function itself has one responsibility which is to answer the question 'isVaraRegistered?'. Any user I/O should be done outside this function.
I have a program which (for now) calculates values of two functions in random points on GPU , sends these values back to host, and then visualizes them. This is what I get, some nice semi-random points:
Now, if I modify my kernel code, and add the local array initalization code at the very end,
__global__ void optymalize(curandState * state, float* testPoints)
{
int ind=blockDim.x*blockIdx.x+threadIdx.x;
int step=blockDim.x*gridDim.x;
for(int i=ind*2;i<NOF*TEST_POINTS;i+=step*2)
{
float* x=generateX(state);
testPoints[i]=ZDT_f1(x);
testPoints[i+1]=ZDT_f2(x);
}
//works fine with 'new'
//float* test_array=new float[2];
float test_array[2]={1.0f,2.0f};
}
I get something like this everytime:
Does anyone know the cause of this behavior? All the drawn points are computed BEFORE test_array is initialized, yet they are affected by it. It doesn't happen when I initialize test_array before the 'for' loop.
Host/device code:
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "curand_kernel.h"
#include "device_functions.h"
#include <random>
#include <iostream>
#include <time.h>
#include <fstream>
using namespace std;
#define XSIZE 5
#define TEST_POINTS 100
#define NOF 2
#define BLOCK_COUNT 64
#define THR_COUNT 128
#define POINTS_PER_THREAD (NOF*TEST_POINTS+THR_COUNT*BLOCK_COUNT-1)/(THR_COUNT*BLOCK_COUNT)
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=false)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
__device__ float g(float* x)
{
float tmp=1;
for(int i=1;i<XSIZE;i++)
tmp*=x[i];
return 1+9*(tmp/(XSIZE-1));
}
__device__ float ZDT_f1(float* x)
{
return x[0];
}
__device__ float ZDT_f2(float* x)
{
float gp=g(x);
return gp*(1-sqrtf(x[0]/gp));
}
__device__ bool oneDominatesTwo(float* x1, float* x2)
{
for(int i=0;i<XSIZE;i++)
if(x1[i]>=x2[i])
return false;
return true;
}
__device__ float* generateX(curandState* globalState)
{
int ind = threadIdx.x;
float x[XSIZE];
for(int i=0;i<XSIZE;i++)
x[i]=curand_uniform(&globalState[ind]);
return x;
}
__global__ void setup_kernel ( curandState * state, unsigned long seed )
{
int id = blockDim.x*blockIdx.x+threadIdx.x;
curand_init ( seed, id, 0, &state[id] );
}
__global__ void optymalize(curandState * state, float* testPoints)
{
int ind=blockDim.x*blockIdx.x+threadIdx.x;
int step=blockDim.x*gridDim.x;
for(int i=ind*2;i<NOF*TEST_POINTS;i+=step*2)
{
float* x=generateX(state);
testPoints[i]=ZDT_f1(x);
testPoints[i+1]=ZDT_f2(x);
}
__syncthreads();
//float* test_array=new float[2];
//test_array[0]=1.0f;
//test_array[1]=1.0f;
float test_array[2]={1.0f,1.0f};
}
void saveResultToFile(float* result)
{
ofstream resultFile;
resultFile.open ("result.txt");
for(unsigned int i=0;i<NOF*TEST_POINTS;i+=NOF)
{
resultFile << result[i] << " "<<result[i+1]<<"\n";
}
resultFile.close();
}
int main()
{
float* dev_fPoints;
float* fPoints=new float[NOF*TEST_POINTS];
gpuErrchk(cudaMalloc((void**)&dev_fPoints, NOF * TEST_POINTS * sizeof(float)));
curandState* devStates;
gpuErrchk(cudaMalloc(&devStates,THR_COUNT*sizeof(curandState)));
cudaEvent_t start;
gpuErrchk(cudaEventCreate(&start));
cudaEvent_t stop;
gpuErrchk(cudaEventCreate(&stop));
gpuErrchk(cudaThreadSetLimit(cudaLimitMallocHeapSize, 128*1024*1024));
gpuErrchk(cudaEventRecord(start, NULL));
setup_kernel<<<BLOCK_COUNT, THR_COUNT>>>(devStates,unsigned(time(NULL)));
gpuErrchk(cudaDeviceSynchronize());
gpuErrchk(cudaGetLastError());
optymalize<<<BLOCK_COUNT,THR_COUNT>>>(devStates, dev_fPoints);
gpuErrchk(cudaDeviceSynchronize());
gpuErrchk(cudaGetLastError());
gpuErrchk(cudaMemcpy(fPoints, dev_fPoints, NOF * TEST_POINTS * sizeof(float), cudaMemcpyDeviceToHost));
gpuErrchk(cudaEventRecord(stop, NULL));
gpuErrchk(cudaEventSynchronize(stop));
float msecTotal = 0.0f;
cudaEventElapsedTime(&msecTotal, start, stop);
cout<<"Kernel execution time: "<<msecTotal<< "ms"<<endl;
saveResultToFile(fPoints);
system("start pythonw plot_data.py result.txt");
cudaFree(dev_fPoints);
cudaFree(devStates);
system("pause");
return 0;
}
Plot script code:
import matplotlib.pyplot as plt;
import sys;
if len(sys.argv)<2:
print("Usage: python PlotScript <filename>");
sys.exit(0);
path=sys.argv[1];
x=[]
y=[]
with open(path,"r") as f:
for line in f:
vals=line.strip().split(" ");
x.append(vals[0]);
y.append(vals[1]);
plt.plot(x,y,'ro')
plt.show();
The basic problem was in code you originally didn't show in your question, specifically this:
__device__ float* generateX(curandState* globalState)
{
int ind = threadIdx.x;
float x[XSIZE];
for(int i=0;i<XSIZE;i++)
x[i]=curand_uniform(&globalState[ind]);
return x;
}
Returning an address or reference to a local scope variable from a function results in undefined behaviour. It is only valid to use x by reference or value within generateX while it is in scope. There should be no surprise that adding or moving other local scope variables around within the kernel changes the kernel behaviour.
Fix this function so it populates an array passed by reference, rather than returning the address of a local scope array. And pay attention to compiler warnings - there will have been one for this which should have immediately set off alarm bells that there was something wrong.
I'm having a really hard time adjusting function to my needs. First of all look at those three files and notice how I have to call f_texture function in main function in order to make it work:
externs.h
#ifndef EXTERNS_H_
#define EXTERNS_H_
extern char t_about[100];
extern int friction;
extern int f_texture(char* ,char*);
#endif
functionA.c
#include <stdio.h>
#include "externs.h"
int main()
{
f_texture("rough","friction");
printf("Friction: %d\n", friction);
f_texture("rough","t_about");
return 0;
}
functionB.c
#include "externs.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
char t_about[100];
int friction;
int f_texture(char* texture,char* what_is_needed)
{
/*Checking if both values are present*/
assert(what_is_needed);
assert(texture);
/*Static array in order to prevent it's disappearance*/
memset(t_about, '\0', sizeof(t_about));
/*Configuring variables for desired texture*/
if (strcmp(texture, "smooth") == 0)
{
strcpy(t_about, "The surface is perfectly smooth, without any "
"protuberances.\n");
friction = 0;
}
else if (strcmp(texture, "rough") == 0)
{
strcpy(t_about, "Rough bumps can be feeled under my fingertips.\n");
friction = 4;
}
/*In case of absent keyword of desired texture it will crash the program*/
else
{
assert(!what_is_needed);
}
/*Returning desired value*/
if (strcmp(what_is_needed, "t_about") == 0)
{
int i=0;
while (t_about[i] != '\0')
{
printf("%c", t_about[i]);
i++;
}
}
else if (strcmp(what_is_needed, "friction") == 0)
{
return friction;
}
/*In case of absent keyword of desired value it will crash the program*/
else
{
assert(!what_is_needed);
}
return 0;
}
And now here is my question: How to rewrite this code to make it possible to call f_texture function without using quotation marks inside? I mean instead of f_texture("abcd","efgh") just to type f_texture(abcd,efgh). I've noticed that this way it's required just after I've wrote this code.
Thanks in advance.
If you don't want to assign string constants to variables or preprocessor object macros, another option is to use preprocessor function macros, using the stringification feature:
#define call_f_texture(a,b) f_texture(#a,#b)
....
call_f_texture(rough,friction);
The C preprocessor will turn this into
f_texture("rough","friction");
You can also use some macros:
#define ROUGH "rough"
#define FRICTION "friction"
#define T_ABOUT "t_about"
int main()
{
f_texture(ROUGH, FRICTION);
printf("Friction: %d\n", friction);
f_texture(ROUGH, T_ABOUT);
return 0;
}
You can do like this,
char rough[]="rough";
char friction[]= "friction";
and call
f_texture(rough, friction);
char a[MAX] = "rouch";
char b[MAX} = "friction";
int main()
{
f_texture();
...
}
int f_texture()
{
/*Checking if both values are present*/
assert(b);
assert(a);
}
or
int f_texture(char* a,char* b)
{
/*Checking if both values are present*/
assert(b);
assert(a);
...
}
int main()
{
char a[MAX] = "rouch";
char b[MAX} = "friction";
f_texture(a,b);
...
}