Use of "while" instead of "for" in C - c

Hello I'm new to programming, and would want to return an array in a "while" condition (not use "for"), any tips to make my program working please? Thanks
int numberPlayer=0;
int *listPlayers= NULL;
int i;
printf("How many players");
scanf("%d",&numberPlayer);
listPlayers= malloc(sizeof(int) * numberPlayer);
if (listPlayers==NULL){
exit(1);
}
i=0;
while(i<numberPlayer){
printf("Joueur n° %d", i*3);
listPlayers[i]= i*3;
i++;
}
while(i<numberPlayer){
printf("%d", listPlayers[i]);
i++;
}

I think you should learn how to use function. return array pointer is available for function not for commands like while, for.
you can check this https://www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm

Your example is a perfect illustration of the superiority of the for loop over the while loop. It is a shame some schools insist on students using only while loops (42, Epita, Epitech...)
You forgot to initialize i = 0 before the second while loop. A classical for loop combines initialization, test and increment in the for clauses, making it easy to read and verify.
For proper output, you should use a separator between the numbers and output a newline.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int main() {
int numberPlayers = 0;
int *listPlayers = NULL;
int i;
printf("How many players? ");
if (scanf("%d", &numberPlayers) != 1) {
return 1;
}
listPlayers = malloc(sizeof(int) * numberPlayers);
if (listPlayers == NULL) {
return 1;
}
i = 0;
while (i < numberPlayers) {
printf("Joueur n° %d? ", i * 3);
if (scanf("%d", &listPlayers[i]) != 1)
return 1;
i++;
}
printf("Liste des joueurs: ");
i = 0;
while (i < numberPlayers) {
printf("[%d]", numberPlayers[i]);
i++;
}
printf("\n");
free(listPlayers);
return 0;
}

Related

CS50 Problem set 2: readability.c help on implementing different functions

Link to question.
I am new to implementing different functions other than main of course. I am having trouble wrapping my head around how to do that because it is not working out for me.
This would be a rather easy solution to put everything into main but I avoided that due to the instructions hinting it's best to create separate functions and overall I think it's cleaner to have the main function just implement your various functions, right?
The problem I was having was getting the respective functions to be able to use other variables so I set some globals up. For some reason I also figured out I could not use a placeholder for the variable when I wanted to test if everything is working fine, instead I had to print the placeholder for the function itself, for e.g printf("%d\n", letter_counter(text) instead of printf("%d\n", letter).
The issue I'm running into now is getting my coleman index function to work, I find that it is not able to print the S value but the L is working fine. Morover, if I call the the letter, word, & sentence function in main (which are commented out right now), this alters my results as well.
I am happy to receive other general pointers you might realize that needs some work. I think I'm just overall confused about getting different functions to work with one another.
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int letter_counter(string text);
int word_counter(string text);
int sentence_counter(string text);
void coleman_liau_formula(string text);
int letter;
int spaces;
int sentences;
int main(void)
{
string text = get_string("Text: ");
//letter_counter(text);
//word_counter(text);
//sentence_counter(text);
coleman_liau_formula(text);
}
// letter counter
int letter_counter(string text)
{
int i; //variable for looping through the string
for (i = 0; i < strlen(text); i++)
{
if (isalpha(text[i]) != 0)
{
letter++;
}
}
return letter;
}
// word counter
int word_counter(string text)
{
int i;
for (i = 0; i < strlen(text); i++)
{
if (isspace(text[i]) != 0)
{
spaces++;
}
}
if (letter == 0)
{
spaces = 0; // by default the program will output 1 word if no letters are inputted. this statement counters that.
return spaces;
}
else
{
return spaces + 1;
}
}
// sentence counter
int sentence_counter(string text)
{
int i = 0;
for (i = 0; i < strlen(text); i++)
{
if (text[i] == '.' || text[i] == '!' || text[i] == '?') //one flaw is that an occurence such as ellipsis would increase the sentence counter
{
sentences++;
}
}
return sentences;
}
void coleman_liau_formula(string text)
{
//float L = ((float) letter_counter(text) / (float) word_counter(text)) * 100;
//float S = ((float) sentence_counter(text) / (float) word_counter(text)) * 100;
//int index = round((0.0588 * L) - (0.296 * S) - 15.8);
/*if (index >=16)
{
printf("Grade 16+\n");
}
else if (index < 1)
{
printf("Before Grade 1\n");
}
else
{
printf("Grade %i\n", index);
}*/
printf("%i\n%i\n%i\n", letter_counter(text), word_counter(text), sentence_counter(text));
}
The counter functions are cumulative. That is if word_counter is called 2 times, it will double the result. That should be all you need to know to make progress.

How to break a while loop when it is false to a certain condition

I was trying to make a program where if I enter an integer, the program would find out the bigger number and subtract it by the smaller number. This part, I got it.
The problem is, the infinite loop part.
I tried to get type in two integers keep on printing with the while loop, and break when at least one character is typed in.
For example, if I type in 2 #, it would break.
But I couldn't find the write place to get the break; within the code and therefore whenever I enter a character it would keep on creating an infinite loop.
Is there any way to create a break in this code? I humbly ask for advice...
The following is the code which I couldn't put the break
(By the way, the reason I did the condition in while as sizeof(i)==4 || sizeof(j)==4 was to make it so it would only enter an integer, since the size of an integer is 4)
int main()
{
int i, j;
int result;
while (sizeof(i)==4 || sizeof(j)==4){
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i){
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
The bottom code is the one I tried to put break but failed (it kept creating an infinite loop)...
int main()
{
int i, j;
int result;
while (sizeof(i)==4 || sizeof(j)==4){
if (sizeof(i) == 4 || sizeof(j) == 4) {
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
else
break;
}
return 0;
}
and here's a code where I got rid of the sizeof and used while(1), though there wasn't much change in the fact that the break didn't work...
int main()
{
int i, j;
int result;
while (1){
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
You can't use sizeof(i) to do run-time checks! This is a compile-time constant that, in your case (32-bit integers) will always evaluate to 4.
In order to check that two valid integers have been given, you can check the return value of the scanf function (it gives the number of fields successfully scanned):
#include <stdio.h>
int main()
{
int i, j;
int result;
while (1) {
printf("type in two integers : ");
if (scanf("%d %d", &i, &j) != 2) break; // Break here if we didn't get two integers
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
Feel free to ask fir further clarification and/or explanation.
Drop the whole concept of endless loop with break inside if.
Make a condition for the loop based on the return value of scanf(), that is practically what it is designed for.
#include <stdio.h>
int main()
{
/* always init everything */
int i=0, j=0;
int result=0;
printf("type in two integers : ");
while (2==scanf("%d %d", &i, &j))
{
if (i < j) {
result = j - i;
}
else /* removed second if, to have a meaningful result for i==j */
{
result = i - j;
}
printf("%d\n", result);
printf("type in two integers : ");
}
return 0;
}
I'd probably actually use do {...} while (...) with a variable storing the return value of scanf()for being used in the loop condition. I'd consider it more elegant for not having to copy the print, but I kept it closer to your code structure.
More comments on your code:
as explained in comments, sizeof() works differently than you seem to think; it is static and does not change at runtime and hence cannot be used in a loop condition
with while (sizeof(i)==4 || sizeof(j)==4){if (sizeof(i) == 4 || sizeof(j) == 4){/* a */} else {/* b */}, b cannot ever be reached, because the conditions of while and if are identical
check the possible outcomes of the if conditions inside the loop, you are leaving the one with i==j undefined and return an uninitialised value
always init all variables as a habit
for a good MRE include the include lines
On your request, here is a proposal for the do-while alternative:
#include <stdio.h>
int main()
{
/* always init everything */
int i=0, j=0;
int result=0;
int iScanned=0;
do
{
printf("type in two integers : ");
iScanned=scanf("%d %d", &i, &j); /* keep the return value for loop */
if (i < j) {
result = j - i;
}
else /* removed second if, to have a meaningful result for i==j */
{
result = i - j;
}
if(2==iScanned) printf("%d\n", result); /* if to avoid awkward last output */
} while (2==iScanned);
return 0;
}

Why doesn't the if statement print 'well done' and why does the loop repeat out questions()

I wanted to make a game where in which you get three turns to guess the selected number, from the computer. However it will never say well done even if you get the number right (already tested using printf statements) and the loop will also mess up by either continuing or running twice.
I've tried removing the break.
I've put in printf statements to check if randomise and questions actually store the correct values and they do.
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <time.h>
int questions() {
int num;
printf("Chose a number between one - ten: ");
scanf("%d",&num);
return num;
}
int randomise() {
int roll;
srand(time(NULL));
roll = rand()%10 + 1;
return roll;
}
int main() {
int chosenNum, enteredNum, i;
chosenNum = randomise();
enteredNum = questions();
for(i = 0; i < 10; i++) {
if(chosenNum != enteredNum) {
questions();
break;
}
else if(chosenNum == enteredNum) {
printf("WELL DONE !!!");
}
}
return 0;
}
Zero errors and Zero warnings. and the outcome should be that you get greeted with well done.
There are two issues:
You are using break which will not allow another attempt to input the number if first number is not matched, and
the return value from questions() in the loop is not assigned to enteredNum (it means it will try old number second time).
enteredNum is never set inside the loop. Thus, it's impossible for the if be false unless it is false the first time.
Fix your loop to something like this instead:
for(i = 0; i < 10; i++){
if(chosenNum != enteredNum){
enteredNum = questions();
break;
}
else if(chosenNum == enteredNum){
printf("WELL DONE !!!");
}
}
This is the most recent update of the code, thanks for all your help guys. The feedback was great ! Heres the code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
int questions(){
int num;
printf("Chose a number between one - ten: ");
scanf("%d",&num);
return num;
}
int randomise() {
int roll;
srand(time(NULL));
roll = rand()%10 + 1;
return roll;
}
int main(){
int chosenNum, enteredNum, i;
int life = 3;
chosenNum = randomise();
enteredNum = questions();
for(i = 0; i < 2; i++){
enteredNum = questions();
if((enteredNum != chosenNum) && life > 0){
life -= 1;
if(life == 1 ){
printf("GAME OVER !!!\n");
break;
}
}
else if((chosenNum == enteredNum) && life > 0){
printf("WELL DONE !!!\n");
break;
}
}
return 0;
}

Why does my C compiler skip the second scanf?

My Programm looks like this.
int main(){
int maxnote = 0;
int eingabewert;
int n = 0;
int userMarks[200];
ind promark;
printf("Welcome, plese enter your points, -1 to finish.\n");
while (eingabewert != -1){
scanf("%d", &eingabewert);
if(eingabewert < -1){
printf("A student can't have 0 > points.\n");
exit(0);
}
userMarks[counter] = eingabewert;
counter += 1;
}
printf("Please insert, the least pints needed for 6:");
//Second Scanf doesn't work, it stays in a Loop or something like that
scanf(" %d", &maxnote);
for(int i = 0; userMarks[i] != -1; i++){
userMarks[i] = berechneNote(userMarks[i], maxnote);
}
countMarks(userMarks);
notenstats(userMarks);
promark = ((suffmark/counter) * 100);
printStatistic(maxnote, promark);
}
The first Scanf() does it job perfectly and takes the given numbers.
However the second one isn't doing that.
It stays in a Loop and I can't go forward with my code.
What should I do to fix this?
Because you are using eingabewert uninitialized in
while (eingabewert != -1){
Initialize it with
int eingabewert = 0;
And always check the result of scanf
while ((eingabewert != -1) && (scanf("%d", &eingabewert) == 1))
You are also using userMarks uninitialized in
for(int i = 0; userMarks[i] != -1; i++){
In this case (an array) initialize it using
int userMarks[200] = {0};
There is a space in the format specifier in the second scanf. And you should learn how to use a debugger, like gdb. It's a lot faster than posting such a long question on SO.

pulling values from pointers in a loop

getLine is a function that gets a line, I'm trying to combine lines together outside the getLine function. When ever I try doing this in a loop it messes up the output. I bet it has to do with the pointers, but I have spend many hours trying to figure it out.
int num;
int matrix[370];
i=1;
j=0;
while(*(point=getLine(infile)) != -2){
n[j]=*point;
if(n[0] != n[j]){
printf("matrix dim error 1");
break;
}
while (i<=n[j]){
matrix[i+(3*j)] = *(point+(i+(3*j)));
i++;
printf("%d", matrix[i+(3*j)]);
}
printf("%d %d %d\n", matrix[1],matrix[2],matrix[3]);
j++;
}
fclose( infile );
}
int *getLine(FILE *infile){
int l=0;
int line[7];
int i=1;
int *point;
while ((l=getNum(infile)) != -1){
if(l==EOF){
line[0]=EOF;
point = &line[0];
return(point);
}
line[i]=l;
i++;
}
if(i==1){
line[0]=-2;
point = &line[0];
return(point);
}
line[0]=(i-1); //stores the length of the line in first space
printf("%d %d %d\n",line[1],line[2],line[3]);
point = &line[0];
printf("%d\n",*point);
return(point);
}
int getNum(FILE *infile) {
int c=0;
int value=0;
while ((c=fgetc(infile)) != '\n') {
if(c==EOF){
return(EOF);
}
if((c==32)||(c==13)){
if(value != 0){ //Making sure a number has been gotten
//printf("%d\n\n", value);
return(value);
}
//otherwise keep getting characters
}
else if ((c<=47)||(c>=58)){
printf("incorrect number input %d\n", c);
exit(1);
}
else {
value = (10*value) + (c - '0');
}
}
return(-1);//flags that the end of line has been hit
}
There is one problem:
int *getLine(FILE *infile){
int line[7];
int *point;
point = &line[0];
return(point);
}
You return a pointer to a local variable. It becomes invalid when you return from the function. You could allocate it instead on the heap, or let the caller provide it as an argument.
Instead of
while (i<=n[j]){
didn't you mean
while (i<=n[j][0]){
More Edit: That's actually ok, i overlook the * in the assignment.
Edit: Some more things:
there is no check that the range of int is not exceeded in getNum
there is no check in getLine that more than 7 values are read (which would blow int line[7]
the matrix calculation in my opinion assumes that there are 3 values read, getLine can deliver up to 7
matrix[i+(3*j)] = *(point+(i+(3*j))); ?? point is only 7 int big!!! so for the second value it will read beyond defined data. Shouldn't it read matrix[i+(3*j)] = point[i];
hth
Mario
BTW: I strongly recommend:
resort to std-lib functions
better naming (i and j in the same source are strongly discouraged)

Resources