Related
Instructions for the Code
You are given a skeleton C program that will sort the input strings (char array) in alphabetical order. The program will first read the number of input n. Then, a for loop will loop n times to read the input string one by one. Finally, it will print the sorted inputs in alphabetical order.
You can assume each word does not contain space and is less than 10 chars, and the total number of input words n is less than 100.
The functionality of reading input and printing words have been done for you. Complete the program by adding the functionality of sorting words.
Hints: 1. For sorting, you should be familiar with Bubble sort. Right? However, here we are swapping the content of two strings instead of integers. 1. As this is a C program, you are unable to use comparators or do assignments for strings like str1 > str2 or str1 = str2 in C++. You have to consider to use the functions in the <string.h> library such as strcmp(), strcpy(), etc...
Example
Input (Assume we want to input 5 words)
5
delta
alfa
apple
charlie
bravo
Output (Note that "apple" is placed after "alfa" as "p" is after "l" in alphabetical order.)
alfa
apple
bravo
charlie
delta
Description of my Question
Is it possible to explain the lines of code in the solution? I do not understand the following:
how do the nested for loops help in sorting the words.
how do the lines involving strcpy and strcmp help in sorting words
why do we denote a * in char *t
Please refer to the following code. I have labelled the parts I do not understand with the format: //Cannot understand: XXXXXXXXXX
#include <stdio.h>
#include <string.h>
int main()
{
// Declare a 2D char array to stores inputs words
// Maximum 100 input words and each word maximum 10 chars
char words[100][10];
char temp[10];
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s", words[i]);
}
// Add codes here to sort words
int i, j;
char *t; //Cannot understand: why *t? What is the use of * here?
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++){ //Cannot understand: why use double for loop here?
if (strcmp(words[j],words[j + 1])>0) { //Cannot understand: FROM HERE
strcpy(temp, words[j]);
strcpy(words[j], words[j+1]);
strcpy(words[j+1], temp); //Cannot understand: TO HERE. How do these lines of strcmp and strcpy help in sorting words?
}
}
}
for (int i = 0; i < n; i++) {
printf("%s\n", words[i]);
}
return 0;
}
Any time you need to sort in C, you should reach for the qsort() function. It can sort an array or allocated block of memory containing any type of object. You simply write a compare function that is passed as the last parameter of qsort() telling it how you want the data sorted.
Writing the compare() function is simple, it has the declaration of:
int compare (const void *a, const void *b);
Where a and b are just pointers to the elements in your array. So what is the element type? In you question they would be arrays of char[10]. So what does that make a and b in compare()? Pointer to array of char[10], or formally char (*)[10].
So your job inside compare() in order to use a and b is simply to cast each to char (*)[10] and then dereference so you are dealing with the original word in array type char[10].
/* a & b are pointers to adjacent arrays in words, (pointers to char[10]) */
const char *sa = *(const char(*)[10])a,
*sb = *(const char(*)[10])b;
Now sa and sb and pointers to the strings that need to be compared. To compare them, you simply loop over the characters until you find the first character between the two that differs (or you reach the end of one of the strings) and your return an int of < 0 if a sorts before b, or > 0 if b sorts before a or 0 if there were no differences between the words.
The full compare could be written as:
#define MAXC 32 /* if you need a constant, #define one (or more) */
...
/* qsort compare function lexagraphically sorts words */
int compare (const void *a, const void *b)
{
/* a & b are pointers to adjacent arrays in words, (pointers to char[MAXC]) */
const char *sa = *(const char(*)[MAXC])a,
*sb = *(const char(*)[MAXC])b;
/* loop advancing a character in each word per-iteration */
for (;; sa++, sb++) {
/* if end of either string or characters differ */
if (*sa != *sb || !*sa)
break;
}
return (*sa > *sb) - (*sa < *sb); /* return sort order */
}
Now all you need to do is fill the words array with your input strings and then pass the array to qsort(), e.g.
qsort (words, n, sizeof *words, compare); /* sort array using compare */
That's it, that's all that is necessary to fully sort the words in words.
When you read the words from the file, you should recognize there is no need to store the number in the first line. Simply read the line with fgets() and discard it. Then using fgets() read each subsequent line (trimming the '\n' character from the end) and increment a counter that you will use to protect your array bounds as well as it telling you how many words were read.
A short example (that increases the number of characters available for each word to 32, 10 is too short), sorts and then outputs the sorted words could be written as:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 32 /* if you need a constant, #define one (or more) */
#define MAXW 100
/* qsort compare function lexagraphically sorts words */
int compare (const void *a, const void *b)
{
/* a & b are pointers to adjacent arrays in words, (pointers to char[MAXC]) */
const char *sa = *(const char(*)[MAXC])a,
*sb = *(const char(*)[MAXC])b;
/* loop advancing a character in each word per-iteration */
for (;; sa++, sb++) {
/* if end of either string or characters differ */
if (*sa != *sb || !*sa)
break;
}
return (*sa > *sb) - (*sa < *sb); /* return sort order */
}
void prnwords (char(*arr)[MAXC], size_t n)
{
for (size_t i = 0; i < n; i++) {
printf (" %s\n", arr[i]);
}
}
int main (void)
{
char words[MAXW][MAXC] = {""};
size_t n = 0;
/* read initial line containing number (discard) */
if (!fgets (words[n], sizeof words[n], stdin))
return 1;
/* read each line storing word in words until EOF or array full */
while (n < MAXW && fgets (words[n], sizeof words[n], stdin)) {
words[n][strcspn(words[n], "\n")] = 0; /* trim \n from word */
n++; /* increment counter */
}
qsort (words, n, sizeof *words, compare); /* sort array using compare */
puts ("\nsorted words:"); /* output sorted list of words */
prnwords (words, n);
}
Example Use/Output
Sending your data to the program on stdin using a heredoc, you could do:
$ ./bin/qsort2dwords << 'eof'
> 5
> alfred
> delta
> alfa
> apple
> charlie
> bravo
> alamo
> eof
sorted words:
alamo
alfa
alfred
apple
bravo
charlie
delta
This approach will be much more efficient (and much more well tested) than you trying to invent your own sort
void split(char array[]) {
int length, length2, half;
char first_half[BUF], sec_half[BUF];
length = strlen(array);
length2 = length / 2;
length -= length2;
strncpy(first_half, array, length - 1);
strncpy(sec_half, (array + length), length2 - 1);
printf("%s\n", first_half);
printf("%s\n", sec_half);
}
If input is "People", it outputs:
Pe0z
plcy etc... Just wondering what's the problem here.
My question is not the same as the question mentioned. I am not trying to insert a word in the middle of another word, I am trying to split a word in half and put the two halves in two strings.
OP's trouble is that first_half[BUF], sec_half[BUF] are not certainly null character terminated - a short coming of strncpy().
strncpy( first_half, array, length);
// printf( "%s\n", first_half );
// alternative limited width print, even if `first_half` lacks a null character.
printf( "%.*s\n", length, first_half );
trying to split a wordstring in half and put the two halves in two strings.
Below is a variable length array (VLA) approach.
I recommend memcpy() as that is often fastest for long strings and lest error prone than strncpy() #Blastfurnace. YMMV.
void split(const char array[]) {
size_t a_length = strlen(array);
size_t l_length = a_length / 2;
size_t r_length = a_length - l_length;
char l_half[l_length + 1], r_half[r_length + 1]; // + 1 for null character
memcpy(l_half, array, l_length);
l_half[l_length] = '\0';
memcpy(r_half, array + l_length, r_length + 1); // +1 for null character
printf("<%s>\n", l_half);
printf("<%s>\n", r_half);
}
size_t, an unsigned type, is the right sized integer type to use for array indexing. int maybe insufficient. Note that strlen() returns type size_t.
If all that is wanted is to print the 2 halves, not much code needed:
void split_print(const char array[]) {
int half = strlen(array) / 2;
printf("%.*s\n", half, array);
printf("%s\n", array + half);
}
One other issue not yet considered is "How do I handle words with an odd number of characters?". It's easy to split 1234 into 12 and 34, but how do you split 123? You must decide how to test for odd/even and decide which half gets the extra character (generally the first half, but it's up to you). You should also consider splitting strings of any size (and validate against processing a NULL pointer or empty-string passed to your function).
To handle checking odd/even length, all you need to do is check the 1st-bit of length on little-endian systems, or for complete portability just use modulo 2. If the 1st-bit (on little-endian) or the result of len % 2 is 0 it's even, otherwise the length is odd. (if odd, just add +1 character to the first half).
If your compiler supports Variable Length Array C99 extensions, the problem becomes simply a matter of declaring the two VLAs and letting the compiler handle the work, e.g.
void split_vla (char *s)
{
if (!s || !*s) { /* validate parameter not NULL or empty-string */
fprintf (stderr, "error: s NULL or empty-string.\n");
return;
}
size_t l = strlen (s),
n = (l % 2 == 0) ? l / 2 : l / 2 + 1;
char s1[n + 1], s2[n + 1]; /* declare VLAs */
memcpy (s1, s, n); /* memcpy chars to each half */
memcpy (s2, s + n, l - n);
s1[n] = 0; /* affirmatively nul-terminate */
s2[l - n] = 0;
printf ("s : %s\ns1 : %s\ns2 : %s\n", s, s1, s2);
}
If it doesn't, you can always dynamically allocate storage for each of the halfs (and if you choose calloc over malloc, then your storage is initialized to all zeros (providing a nul-byte at the end of each half), e.g.
void split_dyn (char *s)
{
if (!s || !*s) { /* validate parameter not NULL or empty-string */
fprintf (stderr, "error: s NULL or empty-string.\n");
return;
}
size_t l = strlen (s),
n = (l % 2 == 0) ? l / 2 : l / 2 + 1;
char *s1, *s2;
/* allocate storage for s1 & s2 and validate allocation */
if (!(s1 = calloc (n + 1, 1)) || !(s2 = calloc (n + 1, 1))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
memcpy (s1, s, n); /* memcpy chars to each half */
memcpy (s2, s + n, l - n);
printf ("s : %s\ns1 : %s\ns2 : %s\n", s, s1, s2);
free (s1); /* don't forget to free the memory you allocate */
free (s2);
}
Either way is fine depending on what your compiler supports. You are free to use malloc and affirmatively nul-terminate as was done in the VLA example. Also be aware that alloca gives similar functionality to what you get with VLAs, but provides a bit more flexibility in the scope for your arrays (not relevant here since the VLAs are declared with function scope but be aware of the additional method). Give both examples a try and let me know if you have further questions.
Example Use/Output
$ ./bin/str_split_half 123456789
s : 123456789
s1 : 12345
s2 : 6789
$ ./bin/str_split_half 1234567890
s : 1234567890
s1 : 12345
s2 : 67890
$ ./bin/str_split_half 1
s : 1
s1 : 1
s2 :
Since I see that there is a concern about performance, I'd say get rid of strncpy altogether.
fist_half[l_length] = '\0';
while(l_length--)
first_half[l_length] = array[l_length];
The same method can be applied to the right side with some index modification.
This way you can get rid of overhead and HEADACES of strncpy.
If you use pointers the code can be even further simplified.
It is enough if you initialize the buffers with 0 as shown in split1(...)
char first_half[BUF] = {0}; // whole buffer is full of zeroes
char sec_half[BUF] = {0};
Then termination will be automatic.
The uninitialized buffer contains random characters.
If buffers are not zeroed the termination is needed as shown in split2(...)
The solutions are as close as possible to the original code. They work for even, odd and empty strings.
Please note the symmetry of the solutions with memcpy and strncpy.
#include <stdio.h>
#include <string.h>
#define BUF 255
void split1(char array[], int bUseMemcpy)
{
/* use zeroed buffers to automatically terminated the copied strings */
int length, length2;
char first_half[BUF] = {0};
char sec_half[BUF] = {0};
length = strlen( array );
length2 = length / 2;
length -= length2;
if(bUseMemcpy)
memcpy( first_half, array, length);
else
strncpy( first_half, array, length);
if(bUseMemcpy)
memcpy( sec_half, (array + length), length2);
else
strncpy( sec_half, (array + length), length2);
printf( "<%s>\n", first_half );
printf( "<%s>\n", sec_half );
}
void split2(char array[], int bUseMemcpy)
{
/* Do not initialize the buffers
Use 0 to terminate the buffers after the copy */
int length, length2;
char first_half[BUF];
char sec_half[BUF];
length = strlen(array);
length2 = length / 2;
length -= length2;
if(bUseMemcpy)
memcpy( first_half, array, length);
else
strncpy( first_half, array, length);
first_half[length]=0; /*zero termination needed, since buffers are not initialized to 0*/
if(bUseMemcpy)
memcpy( sec_half, (array + length), length2);
else
strncpy( sec_half, (array + length), length2);
sec_half[length2]=0; // zero termination
printf( "<%s>\n", first_half );
printf( "<%s>\n", sec_half );
}
int main(void) {
split1("123456789",0);
split1("",1);
split2("people",0);
split2("1",1);
return 0;
}
Output:
<12345>
<6789>
<>
<>
<peo>
<ple>
<1>
<>
There is a simple way to output the string split on 2 separate lines: use printf with the %.*s conversion format. It prints a initial portion of the string argument:
void split(const char *array) {
int half = strlen(array) / 2;
printf("%.*s\n%s\n", half, array, array + half);
}
So I have to scan text from a file into an array, but I am only allowed to use scanf() to achieve this. In the file, there are 22 lines and the longest line is 455 characters long. When I compile, I get various warnings. I have been trying to find a solution but nothings seems to help my list of warnings and errors.
#include <stdio.h>
#include <stdlib.h>
#define NUM_ROWS 22
#define LENGTH_OF_LONGEST_LINE 455
void textInit(char array[]);
int main(void) {
char patty [NUM_ROWS][LENGTH_OF_LONGEST_LINE];
textInit(patty[NUM_ROWS][LENGTH_OF_LONGEST_LINE]);
return 0;
}
void textInit(char array[]) {
int x = 0;
for (x = 0; x < 22; ++x) {
scanf("%455s", array[x]);
}
return;
}
The errors I recieve are:
StPat.c: In function âmainâ:
StPat.c:14:4: warning: passing argument 1 of âtextInitâ makes pointer from
integer without a cast [enabled by default]
textInit(patty[NUM_ROWS][LENGTH_OF_LONGEST_LINE]);
^
StPat.c:9:6: note: expected âchar *â but argument is of type âcharâ
void textInit(char array[]);
^
StPat.c: In function âtextInitâ:
StPat.c:26:7: warning: format â%sâ expects argument of type âchar *â, but
argument 2 has type âintâ [-Wformat=]
scanf("%455s", array[x]);
LENGTH_OF_LONGEST_LINE should be 456 to allow space for the \0 terminator.
The body of the function textInit() expects a 2d array, but the function signature only indicates an array of chars. You should also pass the dimensions of the array to the function, rather than rely on global constants.
When you call the textInit() function, you are attempting to pass a char instead of a 2d array (really, a 2d array name in a function call decays to a pointer to an array). The attempted access is out of bounds.
Finally, in the textInit() function, avoid using magic numbers, as you have in the loop in this function. And you should use size_t for array indices, as it is an unsigned integer type guaranteed to hold any array index.
Here is a modified version of your code:
#include <stdio.h>
#include <stdlib.h>
#define NUM_ROWS 22
#define LENGTH_OF_LONGEST_LINE 456
void textInit(char array[][LENGTH_OF_LONGEST_LINE], size_t rows, size_t cols);
int main(void)
{
char patty [NUM_ROWS][LENGTH_OF_LONGEST_LINE];
textInit(patty, NUM_ROWS, LENGTH_OF_LONGEST_LINE);
return 0;
}
void textInit(char array[][LENGTH_OF_LONGEST_LINE], size_t rows, size_t cols)
{
size_t x = 0;
for (x = 0; x < rows; ++x) {
scanf("%455s", array[x]);
}
return;
}
In addition to the nul-byte catch by Mr. Bowling, you can also make use of fgets to take the input. If you would like to init the entire array, you can pass an array of pointers to type char LENGTH_OF_LONGEST_LINE and initialize the entire array at once. For example:
#include <stdio.h>
#include <string.h>
enum { MAXROWS = 22, MAXLINE = 456 };
size_t textinit (char (*a)[MAXLINE], size_t rows, size_t cols);
int main(void) {
size_t i, n;
char patty [MAXROWS][MAXLINE] = {""};
n = textinit (patty, MAXROWS, MAXLINE);
for (i = 0; i < n; i++)
printf (" string[%2zu] : %s\n", i, patty[i]);
return 0;
}
size_t textinit (char (*a)[MAXLINE], size_t rows, size_t cols)
{
size_t n = 0;
while (n < rows && fgets (a[n], cols, stdin))
{
size_t len = strlen (a[n]); /* get lenght */
if (a[n][len - 1] == '\n') /* check for '\n' */
a[n][--len] = 0; /* overwrite with nul-byte */
n++;
}
return n; /* return number of strings read */
}
Note, that fgets reads up to and including the '\n', so you remove the newline by getting the length of each string read, then testing for, and overwriting the '\n' with a nul-terminating character 0 (or the equivalent '\0').
Also note, if you are on windows, replace size_t with unsigned and %2zu in the printf with simply %2u.
I encountered a problem while testing a code.I define a macro for obtaining the number of elements of an array as follows:
#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])
This macro works fine for counting the number of elements of an array whose initializers match the storage capacity(e.g. int buf[] = {1,2,3};),but not very effective with arrays declared as : int buf[20] = {1,2,3};
Now i know counting array elements like these is pretty easy,but what about large number of elements? How do you count them? counting could be a killer,you know!
Consider the following code:
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize);
int main(void)
{
int dst[20] = { 1,2,3 };
int src[] = { 4,5,6 };
size_t dstSize = 3; // dstSize = ARRAY_SIZE(dst) doesn't work
size_t srcSize = ARRAY_SIZE(src);
g_strcat(dst, dstSize, sizeof(int), src, srcSize);
size_t n, newSize = dstSize + srcSize;
for (n = 0; n < newSize; n++) {
printf("%d ", dst[n]);
}
putchar('\n');
return 0;
}
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize)
{
memcpy((char *)_Dst + (dstSize * bytes), _Src, srcSize * bytes);
}
If you only partially initialize a list of primitive data types (ie: array of ints), the remaining elements get initialized to 0.
C99 Standard 6.7.8.21
If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in
a string literal used to initialize an array of known size than there
are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage
duration.
In your case, you're trying to determine the size of the initializer list. Can't really think of a valid reason to need to do this, but you could simply check when elements start being equal to zero consistently. Of course, this fails if you've deliberately set an element to zero.
The macro you wrote will work correctly (ie: return the number of elements in the array), but it will fail if you use it in a function that accepts a pointer-to-array as an argument, as pointer decay causes sizeof to act differently than one might expect.
All that being said, you can't determine the size of the initializer list in any meaningful sense, unless you do something like so, where you define the initializer list as a macro:
Code Listing
#include <stdio.h>
#define LIST {1,2,3}
int main(void)
{
int i[20] = LIST;
int t[] = LIST;
printf("elements in i: %d\n", sizeof(i)/sizeof(int));
printf("elements in t: %d\n", sizeof(t)/sizeof(int));
return 0;
}
Sample output
elements in i: 20
elements in t: 3
You can minimize wasted memory by putting the throw-away array into a new block scope, ie:
#include <stdio.h>
#define LIST {1,2,3}
int main(void)
{
int i[20] = LIST;
int initListSize = 0;
{
int t[] = LIST;
initListSize = sizeof(t) / sizeof(int);
}
printf("elements in t: %d\n", initListSize);
return 0;
}
This will limit the storage lifetime of the temporary array to the narrow scope between the braces. Again, I can see this being useful maybe as an experiment, but can't see this ever finding its way into production code.
This will do it if we can assume that the last initialized element is not zero (because that's indistinguishable from being implicitly initialized to zero):
size_t trailing_zero_bytes(const void* data, size_t size) {
for (; size > 0; size--) {
if (((const char*)data)[size - 1] != 0) {
break;
}
}
return size;
}
#define ARRAY_SIZE(arr) \
((sizeof(arr) - trailing_zero_bytes(arr, sizeof(arr)) + sizeof(arr[0]) + 1) / sizeof(arr[0]))
If you want to count these two cases differently, you're completely out of luck (unless you parse the code using Clang or GCC-XML or whatever):
int s1[5] = { 4,5,6 }; // 2 zeros implied
int s2[5] = { 4,5,6,0 }; // 1 zero implied
Both of the above will give 3 with my approach, and there is nothing that can be done about it.
Your macro is working fine. The statement:
int dst[20] = { 1,2,3 };
Creates the following in stack memory:
|1|2|3|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
The array size is still 20 even if it has only been initialized with the first three values
Regarding your question in the comments: How will i concatenate to the array? The array must be big enough to hold the other string:
If you are working with strings (and not number arrays) the string function int len = strlen(string); can be used to test the existing usage of a string variable before concatenating.
Unlike the sizeof macro, strlen is a function that looks for the first NULL character in an array of characters:
char string[20] = {"yes"};
Creates the following in memory:
|y|e|s|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
strlen starts at the address of string and counts characters until it encounters the first NULL. (or 0):
int len strlen(string); //will yield a len of 3
you can then use strncat(string, newStr, count); to concatenate a specified numbers of characters, count, to a string of a known capacity, thus avoiding a buffer overflow.
Keep in mind that a string variable of size == 20 for example is limited to containing a string of length == 19. The 20th position must be reserved for the NULL character.
If you want to determine the number of initializers of an array,declare an array to hold the initializers elements and apply the macro ARRAY_SIZE() on it.Then use memcpy() to copy the initializers to the dst[20] array.
Now you have the number of elements without hassle.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize);
int main(void)
{
int dst[20], src[] = { 4,5,6 };
int initializer_list[] = { 1,2,3 };
size_t init_size = ARRAY_SIZE(initializer_list);
memcpy(dst, initializer_list, init_size * sizeof(int));
size_t dstSize = init_size;
size_t srcSize = ARRAY_SIZE(src);
g_strcat(dst, dstSize, sizeof(int), src, srcSize);
dstSize += srcSize;
size_t n;
for (n = 0; n < dstSize; n++) {
printf("%d ", dst[n]);
}
putchar('\n');
return 0;
}
void g_strcat(void *_Dst, size_t dstSize, size_t bytes, const void *_Src, size_t srcSize)
{
memcpy((char *)_Dst + (dstSize * bytes), _Src, srcSize * bytes);
}
I had to delete all the code. What I' looking is how to sprintf all elements of an array in the same line.
The display has 2 lines, I need to print the array 10,24,32,40,51, .....first line
and 10,51 .....second line
sample
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *join(int n, const int array[n], const char *format, const char *sep){
if(!format)
format = "%d";
if(!sep)
sep = ", ";
size_t len = strlen(sep)*(n-1)+1;//+1 for EOS
int i;
for(i=0;i<n;++i)
len += snprintf(NULL, 0, format, array[i]);
char *result = malloc(len);
if(!result)return NULL;
size_t pos = 0;
for(i=0;i<n;++i){
pos += sprintf(result + pos, format, array[i]);
if(i != n-1)
pos += sprintf(result + pos, "%s", sep);
}
return result;
}
int main (void){
int array[][5]={{10,24,32,40,51},{10,1,99,77,88}};
int row_size = sizeof(array)/sizeof(array[0]);
int col_size = sizeof(array[0])/sizeof(int);
char *join_str;
int i;
for(i=0;i<row_size;++i){
char *join_str = join(col_size, array[i], "%2d", ", ");
printf("%s\n", join_str);
free(join_str);
}
return 0;
}
Your array has 10 elements
#define N 10
int V[N] = {10,34, 34, 11};
However, it is partially explicitly initialised so that indices 0, 1, 2 and 3 contain 10, 34, 34 and 11 respectively. A partially explicitly initialised array in C will have the remaining elements (4 .. 9 inclusive) implicitly initialised to 0.
You then:
sprintf (str, "%d %d ... %d %d", V[0], V[1], V[N-2], V[N-1];
This isn't code you are actually running, as it is missing a ), and str is undefined. However, what this would do is write four values to str (not the screen), being values 0, 1, 8 and 9 (i.e. the first 2 and last 2 values), i.e. the characters 0 1 0 0 plus a terminating NULL.
As you are using sprintf() not snprintf() you have no way of checking whether this will overflow str.
It's difficult to tell what you are then doing because of the formatting of the question, but it appears you are calling a function array that might or might not modify the array and print it out again. However, your assembler function is defined as:
__asm void array (int V[], int N, int V) ....
which has an array / pointer parameter called V, a second parameter called N (though the main program #defines this to 10 (so that won't work), and a third parameter also called V which won't work as that's the name of the first parameter.
You also have a mysterious X defined to 10, which is then unused.
It's not particularly clear what you are asking and it would be better if you posted a small working code snippet, but I hope the above is of help.