Cannot assign values to array of pointers in C - arrays

I want to copy my array over to a pointer, so I can sort the array without changing the original. I'm not getting any errors, and am at a dead end. I've tried printing the pointer's contents, but it's always junk data. If anyone could help me it'd be much appreciated.
#include <stdio.h>
void bubbleSort(char *array[], int arrIndex);
void displaySort (char *array[], int arrIndex);
int main (void)
{
int index;
int count = 0;
printf("Enter number of people (0 - 50): ");
scanf("%d", &index);
index -= 1;
char userLastFirst[25][index];
int userAge[index];
//defining pointer
char *namePtr[25][index];
//do while loop, loops while count is less than or equal to the index
do{
printf("Enter name %d (last, first): ", count);
scanf(" %[^\n]s", userLastFirst[count]);
printf("Enter age %d: ", count);
scanf("%d", &userAge[count]);
// printf("\n\n%s %d\n\n", userLastFirst[count], userAge[count]);
count++;
} while (count <= index);
//assigning values to pointer
for(int i = 0; i < index; i++){
namePtr[25][i] = &userLastFirst[25][i];
}
//does not print values of pointer
for(int i = 0; i < index; i++){
printf("value of ptr[%d] = %s\n", i, namePtr[i]);
}
bubbleSort(*namePtr, index);
displaySort(*namePtr, index);
return 0;
}
void bubbleSort(char *array[], int arrIndex)
{
for (unsigned int pass = 0; pass < arrIndex - 1; ++pass) {
for (int i = 0; i < arrIndex - 1; ++i) {
if (array[i] < array[i + 1]) {
int temp = *array[i];
*array[i] = *array[i + 1];
*array[i + 1] = temp;
}
}
}
}
void displaySort(char *array[], int arrIndex)
{
for(int i = 0; i < arrIndex; i++){
printf("%s",*array[i]);
}
}
Sorry it's a lot, but I've looked everywhere, and am not exactly sure what the problem is. I suspect it's how I pass pointers thru the functions, or how I'm using * and & but am not totally sure what I'm doing wrong. The for loop below the one that assigns the array values to the pointer is for testing. It's supposed to print out the values I had given it in the previous for loop, but it doesn't. It just prints junk data.

There are couple of issues here, and since I don't know what exactly you want your final code to look like, I am going to give a few examples of what is wrong and how you could possibly fix that.
char userLastFirst[25][index];
This should be
char userLastFirst[index][25];
You don't want 25 people with names up to index characters in them, but rather index people with names up to 25 characters int them.
char *namePtr[25][index];
should be
char namePtr[index][25];
Same as before + you don't need the * here. Since you decided to go with vla let's stick with it. You would use * and more specifically char ** if you went with malloc/calloc.
namePtr[25][i] = &userLastFirst[25][i];
rather than doing this awkward copying, try:
strcpy(namePtr[i], userLastFirst[i]);
it copies the entire string for you, rather than just a single character. You will need to #include the <string.h> library for that.
void bubbleSort(char *array[], int arrIndex)
The first bubble sort argument should be:
char array[][25] // the same in displaySort
if you want to do it without the hassle of malloc/calloc.
And also don't go with int as your temp type. Rather do char temp[25] and copy them around with strcpy.
And don't compare strings with <, it doesn't work in C. Use strcmp for that.
And that's it for doing it without malloc/calloc, here's an example code:
#include <stdio.h>
#include <string.h>
void bubbleSort(char array[][25], int size);
void displaySort(char array[][25], int size);
int main (void)
{
int num_of_people;
printf("Enter number of people (0 - 50): ");
scanf("%d", &num_of_people);
char original_array[num_of_people][25];
char copied_array[num_of_people][25];
for (int i = 0; i < num_of_people; i++) {
printf("Enter name %d (last, first): ", i);
scanf(" %[^\n]s", original_array[i]);
}
for(int i = 0; i < num_of_people; i++){
strcpy(copied_array[i], original_array[i]);
}
bubbleSort(copied_array, num_of_people);
displaySort(copied_array, num_of_people);
return 0;
}
void bubbleSort(char array[][25], int size)
{
for (int i = 0; i < size - 1; ++i) {
for (int j = 0; j < size - 1 - i; ++j) {
if (strcmp(array[j], array[j + 1]) > 0) {
char temp[25];
strcpy(temp, array[j]);
strcpy(array[j], array[j + 1]);
strcpy(array[j + 1], temp);
}
}
}
}
void displaySort(char array[][25], int size)
{
for(int i = 0; i < size; i++){
printf("%s\n",array[i]);
}
}
and the program work like this:
Enter number of people (0 - 50): 4
Enter name 0 (last, first): Kowalski, Jan
Enter name 1 (last, first): Kowalska, Anna
Enter name 2 (last, first): Nowak, Miłosz
Enter name 3 (last, first): Amper, Ohm
Amper, Ohm
Kowalska, Anna
Kowalski, Jan
Nowak, Miłosz
I hope this is something you wanted to achieve.

Related

Sorting unique vectors in c

The program should eliminate any repeating digits and sort the remaining ones in ascending order. I know how to print unique digits but I don´t know how to create a new vector from them that i can later sort.
#include <stdio.h>
void unique(double arr[], int n) {
int i, j, k;
int ctr = 0;
for (i = 0; i < n; i++) {
printf("element - %d : ",i);
scanf("%lf", &arr[i]);
}
for (i = 0; i < n; i++) {
ctr = 0;
for (j = 0, k = n; j < k + 1; j++) {
if (i != j) {
if (arr[i] == arr[j]) {
ctr++;
}
}
}
if (ctr == 0) {
printf("%f ",arr[i]);
}
}
}
int main() {
double arr[100];
int n;
printf("Input the number of elements to be stored in the array: ");
scanf("%d", &n);
unique(arr, n);
}
You can always break a larger problem down into smaller parts.
First create a function that checks if a value already exists in an array.
Then create a function that fills your array with values. Check if the value is in the array before adding it. If it is, you skip it.
Then create a function that sorts an array. Alternatively, qsort is a library function commonly used to sort arrays.
This is far from efficient, but should be fairly easy to understand:
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUMS 256
int find(double *arr, size_t length, double val)
{
for (size_t i = 0; i < length; i++)
if (val == arr[i])
return 1;
return 0;
}
size_t fill_with_uniques(double *arr, size_t limit)
{
size_t n = 0;
size_t len = 0;
while (n < limit) {
double value;
printf("Enter value #%zu: ", n + 1);
if (1 != scanf("%lf", &value))
exit(EXIT_FAILURE);
/* if value is not already in the array, add it */
if (!find(arr, len, value))
arr[len++] = value;
n++;
}
return len;
}
int compare(const void *va, const void *vb)
{
double a = *(const double *) va;
double b = *(const double *) vb;
return (a > b) - (a < b);
}
int main(void)
{
double array[MAX_NUMS];
size_t count;
printf("Input the number of elements to be stored in the array: ");
if (1 != scanf("%zu", &count))
exit(EXIT_FAILURE);
if (count > MAX_NUMS)
count = MAX_NUMS;
size_t length = fill_with_uniques(array, count);
/* sort the array */
qsort(array, length, sizeof *array, compare);
/* print the array */
printf("[ ");
for (size_t i = 0; i < length; i++)
printf("%.1f ", array[i]);
printf("]\n");
}
Above we read values from stdin. Alternatively, fill_with_uniques could take two arrays, a source and a destination, and copy values from the former into the latter, only when they would be unique.
Remember to never ignore the return value of scanf, which is the number of successful conversions that occurred (in other words, variables assigned values). Otherwise, if the user enters something unexpected, your program may operate on indeterminate values.

C program shows different result in Linux and online compiler

I wrote a program in C to arrange the data in ascending order. When I compiled the code it showed no error but when it runs it shows a very different result than expected. However, when I ran the code in online C compiler it shows the correct result. I entered 5 different numbers 2 ,3 ,1 ,5 ,4.
Result in Linux: 0 1 2 3 4
Result in online compiler: 1 2 3 4 5
Why is this happening?
#include<stdio.h>
int * array(int x[],int l){
int i,j,k;
for(i=0;i<l;i++){
for(j=0;j<l;j++){
if(x[j]>x[j+1]){
k=x[j];
x[j]=x[j+1];
x[j+1]=k;
}
}
}
return x;
}
void main(){
int i,n;
int *b;
printf("enter n\n");
scanf("%d",&n);
int a[n];
for(i=0;i<n;i++)
scanf("%d",&a[i]);
b=array(a,n);
printf("the ascending order is: ");
for(i=0;i<n;i++){
fflush(stdout);
printf("%d\t",b[i]);
}
}
Your code accesses memory beyond your array:
for(j=0;j<l;j++){
if (x[j] > x[j + 1]) {
x[j] = x[j + 1];
x[j + 1] = k;
In your case, when n = 5, you allocate the array for 5 elements with indices 0,1,2,3,4. The latest element of the array is x[4]. But when your code runs and j == l-1, you try to compare and even modify the element x[5]. In fact, your program should crash as it tries to access the "unallocated" memory. But probably because of aligning, the "x[5]" addresses the allocated memory. And, probably, x[5] = 0 on your computer, and your algorithm uses this element as a part of the sorting process. So your function array() returns the array of [0,1,2,3,4,5] and then your main() prints first five elements of this array.
That's why you've got sorted elements [0,1,2,3,4] instead of [1,2,3,4,5].
BTW, the bubble algorithm can be optimized to not touch already sorted elements.
Also, remember the array doesn't copy to pass into the function, the array always passes by its address, so it is not needed to "return" the modified array.
So, the final code can look like:
#include <stdio.h>
void array(int x[], int l)
{
int i, j, k;
for (i = l; i > 1; i--) {
for (j = 1; j < i; j++) {
if (x[j - 1] > x[j]) {
k = x[j - 1];
x[j - 1] = x[j];
x[j] = k;
}
}
}
}
void main()
{
int i, n;
printf("enter n\n");
scanf("%d", &n);
int a[n];
for (i = 0; i < n; i++)
scanf("%d",&a[i]);
array(a, n);
printf("the ascending order is:");
for (i = 0; i < n; i++) {
printf(" %d", a[i]);
fflush(stdout);
}
printf("\n");
}
Of course, there are lots of things to be done in this code, like human-readable variables, formatting, further optimization. But I hope you can do it yourself.
You may find it easier to write programs to get their input from the command line instead of prompting for it. Using C11, you can allocate an array using the length provided by argc, and process the argv array directly:
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
if( argc == 1 ) {
errx(EXIT_FAILURE, "syntax: %s values...", argv[0]);
}
int a[argc - 1];
for( int i=0; i < argc-1; i++ ) {
if( 1 != sscanf(argv[i + 1], "%d", a + i) ) {
errx(EXIT_FAILURE, "could not scan '%s'", argv[i + 1]);
}
}
array(a, sizeof(a)/sizeof(a[0]));
printf("the ascending order is:");
for (i = 0; i < n; i++) {
printf(" %d", a[i]);
fflush(stdout);
}
printf("\n");
}

Function call in C with array

I have a function that takes array 1 and copies/manipulates it to array 2. Basically what it does is take the user input in array one, lets say (2, 3, 3) and array 2 is stored as (2, 0, 3, 0, 3). I know this works because it worked without implementing a function but sadly I have to have one. I cannot for the life of me figure out how to call the function, I believe I don't need a return since its a void and not returning a value. Below is my code any help would be appreciated.
#include <stdio.h>
void insert0(int n, int a1[], int a2[]);
int main() {
int i = 0;
int n = 0;
int a1[n];
int a2[2*n];
printf("Enter the length of the array: ");
scanf("%d",&n);
printf("Enter the elements of the array: ");
for(i = 0; i < n; i++){ //adds values to first array
scanf("%d",&a1[i]);
}
insert0(); //call function which is wrong and I cannot get anything to work
for( i = 0; i < n*2; i++){ //prints array 2
printf("%d", a2[i]);
}
void insert0 (int n, int a1[], int a2[]){ //inserts 0's between each number
for(i = 0; i < n; i++){
a2[i+i] = a1[i];
a2[i+i+1] = 0;
}
}
}
Modifying n after declaraing a1 and a2 won't magically increase their size. Declare a1 and a2 after reading the size into n to use variable-length arrays.
You must pass proper arguments to call insert0.
Defining functions inside functions is GCC extension and you shouldn't do that unless it is required.
a2 should have n*2 - 1 elements, not n*2 elements.
After moving it out of main(), i is not declared in insert0, so you have to declare it.
You should check if readings are successful.
Corrected code:
#include <stdio.h>
void insert0(int n, int a1[], int a2[]);
int main() {
int i = 0;
int n = 0;
printf("Enter the length of the array: ");
if(scanf("%d", &n) != 1){
puts("read error for n");
return 1;
}
if(n <= 0){
puts("invalid input");
return 1;
}
int a1[n];
int a2[2*n-1];
printf("Enter the elements of the array: ");
for(i = 0; i < n; i++){ //adds values to first array
if(scanf("%d", &a1[i]) != 1){
printf("read error for a1[%d]\n", i);
return 1;
}
}
insert0(n, a1, a2);
for( i = 0; i < n*2-1; i++){ //prints array 2
printf("%d", a2[i]);
}
}
void insert0 (int n, int a1[], int a2[]){ //inserts 0's between each number
int i;
for(i = 0; i < n; i++){
a2[i+i] = a1[i];
if (i+1 < n){ // don't put 0 after the last element
a2[i+i+1] = 0;
}
}
}

Recursive function for finding same numbers on same positions between two arrays

Here is an example of what the result should be :
1234 and 1344 Have two numbers on same positions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Proverka(int *num1[], int *num2[], int len, int pom)
{
if (len < 1 && pom < 1)
return 0;
if (*num1 == *num2)
return 1 + Proverka(num1++, num2++, len-1, pom-1);
else {
return Proverka(num1++, num2++, len-1, pom-1);
}
}
int main (void)
{
int *num1[5], *num2[5], pom, len, i, sin, j;
pom = sizeof(num1) / sizeof(num1[0]);
len = sizeof(num2) / sizeof(num2[0]);
for (i = 0; i < pom; i++) {
printf("Enter elements for first array :");
scanf("%d", num1[i]);
}
for (j = 0; j < len; j++){
printf("Enter elements for second array : ");
scanf("%d", num2[j]);
}
sin = Proverka(num1, num2, pom, len);
{
printf("They have %d numbers on same positions", sin);
}
return 0;
}
You have quite a lot of bugs in the code, here's a working version of it.
Read comments to understand what I changed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int Proverka(int *num1, int *num2, int len1, int len2)
{
if (len1 < 1 && len2 < 1) return 0;
// note the pre-increment. Your post-increment wouldn't have worked. Or just add 1.
return (*num1 == *num2) + Proverka(++num1, ++num2, len1 - 1, len2 - 1);
// this works, since "boolean" is really just 0 or 1
}
int main (void)
{
// I make array of ints, not of pointers to ints.
int num1[5], num2[5], len1, len2, i, same;
len1 = sizeof(num1) / sizeof(num1[0]);
len2 = sizeof(num2) / sizeof(num2[0]);
for (i = 0; i < len1; i++) {
printf("First array element %d:", i+1);
scanf("%d", &num1[i]); // pointer at the element
}
for (i = 0; i < len2; i++){
printf("Second array element %d:", i+1);
scanf("%d", &num2[i]);
}
// get pointers at the first array elements
same = Proverka(&num1[0], &num2[0], len1, len2);
printf("They have %d numbers on same positions\n", same); // newline - good practice
return 0;
}
Here's a bit more "optimized" and cleaned up version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ITEMS 5
int Proverka(const int *aa, const int *bb, const int len)
{
if (len == 0) return 0;
return (*aa == *bb) + Proverka(1 + aa, 1 + bb, len - 1);
}
int main (void)
{
int aa[ITEMS], bb[ITEMS], i, same;
for (i = 0; i < ITEMS; i++) {
printf("First array element %d:", i+1);
scanf("%d", &aa[i]);
}
for (i = 0; i < ITEMS; i++) {
printf("Second array element %d:", i+1);
scanf("%d", &bb[i]);
}
same = Proverka(&aa[0], &bb[0], ITEMS);
printf("They have %d numbers on same positions\n", same);
return 0;
}
Using recursion for this is not a very good choice, a loop would be easier and safer. But this works too - for not-too-large arrays.
int *num1[5],*num2[5] ... doesnt give you an array of integer pointers with memory allocated. Fix that. Allocate memory using malloc.
Or just say int num1[5],num2[5] and scanf("%d",&num1[i]);

Sorting an array in C

I'm trying to sort elements in an array from smallest to largest that a user inputs along with the size. This is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAXVALUES 20
void sort(int *A[], int n) {
int i, tmp, j;
for (i = 0; i <= (n - 2); i++) {
for (j = (i + 1); j <= (n - 1); j++) {
if (*A[i] > *A[j]) {
tmp = *A[i];
*A[i] = *A[j];
*A[j] = tmp;
}
}
}
return;
}
int main(int argc, char *argv[]) {
int n, A[MAXVALUES], i;
printf("Enter an array and no. of elements in array: ");
scanf("%d%d", &A[MAXVALUES], &n);
sort(A[MAXVALUES], n);
printf("Ordered array is: \n");
for (i = 0; i <= (n - 1); i++) {
printf(" %d", A[i]);
}
return 0;
}
The compiler compiles it without any errors but it stops working after I put in the inputs. I've yet to quite grasp the theory behind arrays and pointers so could someone tell me where in my code I'm going wrong?
scanf("%d%d", &A[MAXVALUES], &n); is the problem
That's not how you read an array.
First you read the n, after that inside a loop you read every element like
scanf("%d", &A[i]); where i is the index from 0 to n
EDIT:
scanf("%d", &n);
int i = 0;
for(i = 0; i < n; i++)
{
scanf("%d", &A[i]);
}
This is what you want.
You can't use scanf() to read in a whole array at once.
This:
scanf("%d%d", &A[MAXVALUES], &n);
Makes no sense; it passes scanf() the address of the element after the last one in A, causing undefined behavior. The sort() call is equally broken.
To read in multiple numbers, use a loop. Also, of course you must read the desired length first, before reading in the numbers themselves.
Firstly I'll tell you a couple of things about your sorting function. What you want, is take an array (which in C is representable by a pointer to the type of elements that are in that array, in your case int) and the array's size(int) (optionally you can take a sorting method as an argument as well, but for simplicity's sake let's consider you want to sort things from lowest to highest). What your function takes is a pointer to an array of integers and an integer (the second argument is very much correct, or in other words it's what we wanted), but the first is a little more tricky. While the sorting function can be wrote to function properly with this argument list, it is awkward and unnecessary. You should only pass either int A[], either int *A. So your function header would be:
void sort1(int *A, int n);
void sort2(int A[], int n);
If you do this however, you have to give up some dereferencing in the function body. In particular I am referring to
if (*A[i] > *A[j]) {
tmp = *A[i];
*A[i] = *A[j];
*A[j] = tmp;
} which should become
if (A[i] > A[j]) {
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
You should check out the operators [] and *(dereference) precedence http://en.cppreference.com/w/c/language/operator_precedence
Now, to adapt to these changes (and further correct some code) your main would look like so:
int main(int argc, char *argv[])
{
int A[MAXVALUES], n;
do{
printf("n="); scanf("%d", &n);
}while(n < 0 || n > 20);
int i;
for(i = 0; i < n; ++i)
scanf("%d", &A[i]); //this will read your array from standard input
sort(A, n); //proper sort call
for(i = 0; i < n; ++i)
printf(" %d", A[i]);
printf("\n"); //add a newline to the output
return 0;
}

Resources