I have a problem with a character array in my c program.
The program immediately shutdown when I run it. I think the problem is somewhere with passing the character array in the function.
here's my code:
#include<stdio.h>
#include<string.h>
#define DAGEN 7
void inlezen(int[][DAGEN], char[][12]);
int main(void)
{
int i;
int temp[1][DAGEN];
char dagen[7][12];
strcpy(dagen[0], "MA");
strcpy(dagen[1], "DI");
strcpy(dagen[2], "WOE");
strcpy(dagen[3], "DO");
strcpy(dagen[4], "VR");
strcpy(dagen[5], "ZA");
strcpy(dagen[6], "ZO");
inlezen(temp, 1, DAGEN, dagen, 7, 12);
}
void inlezen(int t[][DAGEN], char d[][12])
{
int i;
for (i = 0; i < DAGEN; i++)
{
printf("Geef de temperatuur overdag van %s", d[i]);
scanf("%d%*c", &t[0][i]);
}
for (i = 0; i < DAGEN; i++)
{
printf("Geef de temperatuur 's avonds van %s", d[i]);
scanf("%d%*c", &t[1][i]);
}
}
I've edited my code, but it still doesn't work.
In your code
strcpy(dagen[6], "ZO");
you're accessing out of bound memory by using 6 as the index value. Your definition of dagen
char dagen[6][12];
only permits a valid access up to 5 as the first index.
]
By using 6, it invokes undefined behaviour.
FWIW, C uses 0 based indexing for arrays.
That said, the call
inlezen(temp, 1, DAGEN, dagen, 6, 12);
does not match the function signature, at all.
Finally, scanf() family expects a pointer to variable type of arguments for supplied format specifiers, so, the
scanf("%d%*c", t[0][i]);
statements should be actually
scanf("%d%*c", &t[0][i]);
and likewise.
void inlezen(int[][DAGEN], char[][12]);
See this prototype you declared
and what values you pass to it -inlezen(temp, 1, DAGEN, dagen, 6, 12); in main.
And this strcpy(dagen[6], "ZO"); .Declaration of array was char dagen[6][12]; so index can go from 0 to 5.You access out of bound memory ,thus invokes UB.Either remove this line or increase size to char dagen[7][12];
These statements -
scanf("%d%*c", t[0][i]);
.....
scanf("%d%*c", t[1][i]);
should be -
scanf("%d",&t[0][i]);
.....
scanf("%d",&t[1][i]);
Related
I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)
I have two strings and need to compare them AND state which characters are correct.
My code is:
char Palavra = "exemplo";
int Tamanho = strlen(Palavra),i;
printf("Which is your guess?\n");
char Palpite[Tamanho];
fgets(Palpite,Tamanho,stdin);
char Mensagem[50];
strcpy(Mensagem,"The following characters are correct: ");
for(i=0;i<=Tamanho;i++){
if(Palavra[i] == Palpite[i]) sprintf(Mensagem,"%s %i",Mensagem,i+1);
}
printf("%s",Mensagem);
I need to compare variables Palavra and Palpite, character per character and then say with one is correct.
Something like this:
Palavra = celular
Palpite = cilular
Answer should be: "The following characters are correct: 1 3 4 5 6 7"
But I am getting: "The following characters are correct: 1 3 4 5 6 8"
Any help would be greatly appreciated.
Probably it does not work because you have assigned a pointer to an array to a char value.
Also it could be that you are stepping out of array bounds with for i<=Tamnho is causing some comparison problems/possibly crashes (if you are trying to change them).
But the logic behind the code is correct, so I don't see any other reason as to why it does not work
Maybe this is the issue:
int Tamanho = strlen(Palavra),i;
...
for(i=0;i<=Tamanho;i++){
if(Palavra[i] == Palpite[i]) ... do something
}
Palvara[Tamanho] is going to be a null char. Valid indices for Palvara with a non-null character are from [0..Tamanho-1]. This corrects the bug:
for(i=0; i < Tamanho; i++){
if(Palavra[i] == Palpite[i]) ... do something
}
Also, don't forget that Palpite's length might be less than Palvara's length. Make sure you break out of your for-loop before dereferencing Palpite[i] if i >= strlen(Palpite)
Better:
int len = strlen(Palpite);
int count = (Tamanho <= len) ? Tamanho : len;
for(i=0; i < count; i++){
if(Palavra[i] == Palpite[i]) ... do something
}
It worked as expected with this code, although that last if is a clear work around I am not really confortable using.
int Tamanho = strlen(Palavra),i;
printf("Which is your guess?\n");
char Palavra = "exemplo";
char Palpite[Tamanho];
fgets(Palpite,Tamanho,stdin);
char Mensagem[50];
strcpy(Mensagem,"The following characters are correct: ");
for(i=0; i<=Tamanho; i++) {
if(Palavra[i] == Palpite[i]) {
if(i==Tamanho) {
sprintf(Mensagem,"%s %i",Mensagem,i);
} else {
sprintf(Mensagem,"%s %i",Mensagem,i+1);
}
}
}
printf("%s",Mensagem);
Code incurs undefined behavior (UB) due to attempting to access outside an array's range.
When i==Tamanho, Palpite[i] is bad.
char Palpite[Tamanho];
for(i=0;i<=Tamanho;i++){
if(Palavra[i] == Palpite[i]) sprintf(Mensagem,"%s %i",Mensagem,i+1);
}
Code incurs undefined behavior (UB) due to attempting to access access and write to the same array with int sprintf(char * restrict s, const char * restrict format, ...);. The restrict is a contract that the caller broke by using the destination as an later augment.
sprintf(Mensagem,"%s %i",Mensagem,i+1);
// ^^^^^^^^ ^^^^^^^^ UB
Alternative code could have written to the end.
size_t len = strlen(Mensagem);
sprintf(Mensagem + len," %i",i+1);
Better code would use snprintf() to issue no buffer overrun.
A well warning enabled compiler would have warned about the type mismatch. Save time, enable all warnings.
char Palavra = "exemplo";
UB for writing outside arrays bounds. char Mensagem[50]; is too small for "The following characters are correct: 1 3 4 5 6 8" which needs 51.
Consider scaling Mensagem[]; with a more geneorus size and use snprintf() to avoid overflow.
I have done my school assignment, and I try to fix it by the tutor's comment. However, from my tutor latest email, he points out that "It is luck if it works without making this change. With local variables, you have no idea what is in them by default." I just have no idea what the default is in my code
This is my tutor's comment:
1. The question said only local variables should be used.
The read function was supposed to read in as well as do validation of the length of the input string. Lines 14 and 15 should be inside the read function, not in main.
Because you used text as a global variable, you have been able to write your functions without the need for the string parameters s, st and str. The whole point of this assignment was to test your ability to program with string parameters. While your functions appear to have string parameters, they might as well not be there with text global and only text in the code inside the functions. The read function should be written in terms of s, not text. The count function should be written in terms of st, not text. The justify function should be have str wherever you have text. You have not shown that you understand how string parameters are used.
#include<stdio.h>
#include<string.h>
void read(), justify(char *str, int g);
int count(char *st);
int main(){
char text[100];
int gaps, i;
gaps = 0;
for(i=0; i<3; i++) {
read(text);
gaps = count(text);
justify(text, gaps);
printf("\n");
}
}
void read(char *s){
int length;
printf("Enter a line of text: ");
gets(s);
length = strlen(s);
while(length!=0){
if(length<46){
printf("123456789012345678901234567890123456789012345\n");
length = 0;
} else {
printf("Enter a line of text: ");
gets(s);
length = strlen(s);
}
}
}
int count(char *st){
int num, i, num2;
num = 0;
num2 = strlen(st);
for(i=0; i<num2; i++){
if(st[i]==' '){
num++;
}
}
return num;
}
void justify(char *str, int g){
int i, j, num, m, n, temp;
temp = strlen(str);
num = 45 - temp;
m = num / g;
n = num % g;
for(i=0; i<temp; i++){
printf("%c", str[i]);
if(str[i]==' '){
for(j=0; j<m; j++){
printf(" ");
}
if(n!=0){
printf(" ");
n--;
}
}
}
printf("\n");
}
I would like to learn how to improve the code and make it work without luck. Cheers!
Regarding the title, “What is in local variables by default?”
Nothing. Per C 2018 6.7.9 10, “If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.” (What you think of as a “local variable” is an object with automatic storage duration.) Per 3.19.2, an indeterminate value is either an unspecified value or a trap representation. Per 3.19.3, the C standard imposes no requirements on which value is chosen in any instance.
Consider:
int x;
printf("%d", x);
printf("%d", x);
In these two instances, the printf may print different numbers. The value of x is unspecified in any instance. The program is broken.
Furthermore, there is a rule in 6.3.2.1 2 that amounts to: If you use an uninitialized local variable and its address has never been taken, the behavior of the program is not defined by the C standard. This means, not only can the variable appear to have different values at different times, but that the C standard does not define the behavior of the program at all. The printf statement will not necessarily print. The program could crash. The program could call entirely different routines from what you expect. The C standard imposes no requirements.
Solution: Initialize your local variables by writing = SomeInitialValue when declaring them, as in int x = 0;, or by assigning them values before using them.
1. The question said only local variables should be used.
Solution: Use only local variables. Remove global variables from your program. If a routine needs data from a caller, pass it with a parameter.
2. The read function was supposed to read… Lines 14 and 15…
Lines 14 and 15 in the code in your question do not appear to correspond to lines that should be in the read function. You appear to have put code in the question that differs from what the tutor was referring to.
Solution: Put exactly the code the tutor reviewed in the question. Follow the tutor’s instructions.
3. Because you used text as a global variable…
See both 1. and 2. above. As with 2., the code does not match this comment; you appear to have shown different code from what the tutor reviewed. Show the exact code in the question, and do not use global variables.
I am new in c programming and I am studying arrays right now. I saw that unlike java you can't print them automatically by using Arrays.toString() method. I want to write a simple function that prints the array.
In the program it asks us the size of the array and when we write it, it asks what is the value for each element and then the program calls the displayArray() function to print the array on a single line.
For example :
Hello. What will be the size of the new array?
3
Enter the 1. element
7
Enter the 2. element
5
Enter the 3. element
1
The result should be "Your array is: 7 5 1" but instead of that I get "Your array is: 3 6356728 2" as a result. Can you help?
#include <stdio.h>
void displayArray();
int main()
{
int size;
printf("Hello. What will be the size of the new array?\n");
scanf("%d", &size);
int myarray[size];
for (int i = 0; i < size; i++)
{
printf("Enter the %d. element\n" , (i + 1));
scanf("%d", &myarray[i]);
}
displayArray(myarray[size], size);
return 0;
}
void displayArray(int myarray[], int size)
{
printf("Your array is: ");
for (int i = 0; i < size; i++)
{
printf("%d ", myarray[i]);
}
return;
}
You have a problem in the function call (which your compiler should have warned you about, read the footnote later)
displayArray(myarray[size], size);
should be
displayArray(myarray, size);
because,
Type mismatch between formal parameter and actual argument: you function expects an array (a pointer to the first element of the array, to be precise), not an element of the array.
undefined behavior. For an array defined as int myarray[size], accessing element like myarray[size] is off-by-one, as C arrays are 0-based indexing.
Footnote:
If you try to compile your code, compiler should complain about the mismatch. It can happen either
You did not turn up the compiler warning level (which is a mistake from your side)
or, you chose to ignore the warnings (which is an "offense" from your side)
It's a common mistake which beginners commit.
While calling a function in which you pass an array, you only need to specify the name of the array you want to pass.
Please give me some feedback on how to make my code better or more efficient. It should convert a decimal integer to binary.
#include <stdio.h>
binarydigits(int div, int dis)
{
int numit;
numit=0;
do
{
++numit;
div /= dis;
}
while (div!=1);
++numit;
return numit;
}
main()
{
int x, nb, i;
printf("\n Input an decimal integer number to be converted: ");
scanf("%d", &x);
fflush(stdin);
if (x==0 || x==1)
{
printf("\n\n %d in binary : %d", x, x);
}
else
{
printf("\n\n %d in binary : ", x);
nb = binarydigits(x, 2);
// the function 'binarydigits' returns how many binary digits are needed to represent 'x'
int remind[nb];
// an array of 'nb' elements is declared. Each element of this array will hold a binary digit
for(i=(nb-1) ; i>=0 ; --i, x/=2)
{
remind[i] = x%2;
}
//this 'for' structure saves the remainder of 'x/2' (x%2) in an element of the 'remind[nb]' array
for (i=nb ; i>0 ; --i)
{
printf("%d", remind[nb-i]);
}
//this 'for' structure prints the elements of the 'remind[nb]' array in increasing order
}
getch();
return 0;
}
Any tips on how to make this better would be nice.
Firstly, binarydigits should have a return type int. This is because you return an integer variable numit at the end of this function. Change your function header to:
int binarydigits(int div, int dis)
Secondly, the main() function needs to have a return type int by definition in C, and C++ for that matter. Without it, your compiler will produce a warning, something similar to:
main.c:18:1: warning: return type defaults to 'int' [-Wimplicit-int]
main()
^~~~
Here is a snippet from the the C11 standard (ISO/IEC 9899:2011) on the definition of the main() function:
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters: - Return Type of main()
int main(void) { /* ... */ }
Thirdly, you should remove fflush(stdin) because using the fflush() for stdint is undefined behavior as it is not a part of standard C. From C11 7.21.5.2, fflush works only with output/update stream, not input stream:
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined. - fflush(stdin)
How to make my code better or more efficient?
My advice to you is to stop trying to learn C by trial-and-error method. You should obtain a good book and study it first. It is impossible to create a fast and efficient C program without mastering pointers, bitwise operators and memory manipulations.
Simply, to make your code fast, you should completelly delete your code (I am not going to list all of your bad-practice things here) and start understanding my example:
int main(void){
char *s = (char*)malloc(33);
char *t = s;
int a;
s += 33;
*s = 0;
printf("Enter a number: ");
scanf("%d", &a);
printf("That number in binary: ");
while(a){
*(--s) = a & 1 ? '1' : '0';
a >>= 1;
}
printf("%s\n", s);
free(t);
return 0;
}
Explanation: we have pointer (if you don't know pointers, well you should probably first learn them) s which points to the end of a string. While number from input (number a) is nonzero, we put its last binary digit in the string, decrease pointer and divide a integrally by 2 (this is a >>= 1 instruction). When a is 0, just print the string.