C 编程/习题解答
外观
< C 编程
- include<stdio.h>
- define a5+2
Into main() {
Into ans;
Ans=a*a*a; Printf("%d",c) ; Return 0; }
3. 给出一个在 C 中无法使用的变量名的例子。为什么它不能使用?
- 不,变量名必须以字母(小写或大写)或下划线开头。
- 只有下划线可以使用。
- 例如,#nm*rt 不允许,因为 # 和 * 不是变量名有效的字符。
#include <stdio.h> #include <stdlib.h> main() { int a, b, c, max; #ifdef __WIN32 system("cls"); // for Windows #else system("clear"); // for Unix and Linux #endif printf("\n enter three numbers "); scanf(" %d %d %d ",&a,&b,&c); max = a; if(max < b) max = b; if(max < c) max = c; printf("\n largest=%d \n",max); getchar(); }
1.1. 在你的电脑上,每个数据类型需要多少内存?
- 3 个数据类型:long int、short int、float。
- 在我的电脑上
- long int:4 字节
- short int:2 字节
- float:4 字节
- 我们不能使用 'int' 或 'float' 作为变量名。
- 将 3.14 赋值给 pi 的标准方法是
double pi;
pi = 3.14;
- 由于 pi 是一个常量,良好的编程习惯要求它在运行时不可变。如果你使用以下两行中的任何一行,你将获得额外奖励
const float pi = 3.14;
#define pi 3.14
- 是的,例如
int a = 67;
double b;
b = a;
- 是的,但需要进行强制类型转换,并且 double 会被截断
double a=89;
int b;
b = (int) a;
pi2 = pi;
- 反过来,
pi = pi2;
是一条有效的 C 语句,如果pi
不是常量且pi2
已初始化。 - a.
pi2 = 3.1415;
b. 反过来:3.1415 = pi2;
无效,因为无法将值赋给字面量。
一个可能的解决方案可能是
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[81]; // A string of upto 80 chars + '\0'
int i;
puts("Please write a string: ");
fgets(s, 81, stdin);
puts("Your sentence in reverse: ");
for (i= strlen(s)-1; i >= 0; i--)
{
if (s[i] == '\n')
continue; // don't write newline
else
putchar(s[i]);
}
putchar('\n');
return 0;
}
#define __STDC_WANT_LIB_EXT1__ 1 // Active C11 extended functions (this case is gets_s)
#include<stdio.h>
int slen(const char *); // I don't want to include whole string lib just for get size
int main(void) {
char s[500];
printf("%s","Enter a sentence: ");
if(!gets_s(s,500)) {
puts("Error!");
getchar();
return 0;
}
for(int i=0;i<slen(s);i++)
if(s[i]!=32)
putchar(s[i]);
else
putchar(10);
putchar(10);
getchar();
return 0;
}
int slen(const char *s) {
int i;
for(i=0;s[i]!=0;i++);
return i;
}
一个可能的解决方案
#include<stdio.h>
int main(void) {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) {
for(int j=0;j<=i;j++)
putchar(42);
putchar(10);
}
while((n=getchar())!=10);
getchar();
return 0;
}
一个可能的解决方案
#include<stdio.h>
int main(void) {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) {
for(int j=0;j<=i;j++)
putchar(42);
putchar(10);
}
while((n=getchar())!=10);
getchar();
return 0;
}
一个可能的解决方案
#include<stdio.h>
// This is the fastest way
int main(void) {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) {
for(int j=0;j<=i;j++)
putchar(42);
putchar(10);
}
for(int i=n-1;i>0;i--) {
for(int j=0;j<i;j++)
putchar(42);
putchar(10);
}
while((n=getchar())!=10);
getchar();
return 0;
}
或者像这样(全部是数学运算)
void sideways(int n)
{
int i=0,j=0;
for(i=1;i<2*n;i++){
for(j=1;j<=(n-(abs(n-i)));j++){
printf("*");
}
printf("\n");
}
}
一个可能的解决方案
void right_side_up(int n)
{
int x,y;
for (y= 1; y <= n; y++)
{
for (x= 0; x < n-y; x++)
putchar(' ');
for (x= (n-y); x < (n-y)+(2*y-1); x++)
putchar('*');
putchar('\n');
}
}
另一个解决方案
#include<stdio.h>
int main(void) {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) {
for(int j=0;j<n-i-1;j++)
putchar(32);
for(int j=0;j<i*2+1;j++)
putchar(42);
putchar(10);
}
while((n=getchar())!=10);
getchar();
return 0;
}
// to compile: gcc -Wall prime.c -lm -o prime
#include <math.h> // for the square root function sqrt()
#include <stdio.h>
int is_prime(int n);
int main()
{
printf("Write an integer: ");
int var;
scanf("%d", &var);
if (is_prime(var)==1) {
printf("A prime\n");
} else {
printf("Not a prime\n");
}
return 1;
}
int is_prime(int n)
{
int x;
int sq= sqrt(n)+1;
// Checking the trivial cases first
if ( n < 2 )
return 0;
if ( n == 2 || n == 3 )
return 1;
// Checking if n is divisible by 2 or odd numbers between 3 and the
// square root of n.
if ( n % 2 == 0 )
return 0;
for (x= 3; x <= sq; x += 2)
{
if ( n % x == 0 )
return 0;
}
return 1;
}
另一个更好的解决方案,不需要包含 math.h 并且比上面的解决方案更快。
#include<stdio.h>
int isPrime(const unsigned long long int);
int main(void) {
unsigned long long n;
scanf("%llu",&n);
printf("%d\n",isPrime(n));
while((n=getchar())!=10);
getchar();
return 0;
}
int isPrime(const unsigned long long int x) {
if(x<4)
return x>1;
if(x%2==0||x%3==0)
return 0;
for(unsigned long int i=5;i*i<=x;i+=6)
if(x%i==0||x%(i+2)==0)
return 0;
return 1;
}
一个可能的解决方案,在阅读在线对递归归并排序的描述后,例如 Dasgupta
// to compile: gcc -Wall rmergesort.c -lm -o rmergesort
/*
============================================================================
Name : rmergesort.c
Author : Anon
Version : 0.1
Copyright : (C)2013 under CC-By-SA 3.0 License
Description : Recursive Merge Sort, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//const int MAX = 200;
const int MAX = 20000000;
int *b;
int printOff = 0;
// this debugging print out of the array helps to show
// what is going on.
void printArray(char* label, int* a, int sz) {
int h = sz/ 2;
int i;
if (printOff) return;
printf("\n%s:\n", label);
for (i = 0; i < h; ++i ) {
printf("%d%c", a[i],
// add in a newline every 20 numbers
( ( i != 0 && i % 20 == 0 )? '\n': ' ' ) );
}
printf(" | ");
for (;i < sz; ++i) {
printf("%d%c", a[i],
( ( i != 0 && i % 20 == 0 )? '\n': ' ' ) );
}
putchar('\n');
}
void mergesort(int* a, int m ) {
printArray("BEFORE", a, m);
if (m > 2) {
// if greater than 2 elements, then recursive
mergesort(a, m / 2);
mergesort(a + m / 2, m - m / 2);
} else if (m == 2 && a[0] > a[1]) {
// if exactly 2 elements and need swapping, swap
int t = a[1];
a[1] = a[0];
a[0] = t;
goto end;
}
// 1 or greater than 2 elements which have been recursively sorted
// divide the array into a left and right array
// merge into the array b with index l.
int n = m/2;
int o = m - n;
int i = 0, j = n;
int l = 0;
// i is left, j is right ;
// l should equal m the size of the array
while (i < n) {
if ( j >= m) {
// the right array has finished, so copy the remaining left array
for(; i < n; ++i) {
b[l++] = a[i];
}
// the merge operation is to copy the smaller current element and
// increment the index of the parent sub-array.
} else if( a[i] < a[j] ) {
b[l++] = a[i++];
} else {
b[l++] = a[j++];
}
}
while ( j < m) {
// copy the remaining right array , if any
b[l++] = a[j++];
}
memcpy(a, b, sizeof(int) * l );
end:
printArray("AFTER", a, m);
return;
}
void rand_init(int* a, int n) {
int i;
for (i = 0; i < n; ++i ) {
a[i] = rand() % MAX;
}
}
int main(void) {
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
// int N = 20;
// int N = 1000;
// int N = 1000000;
int N = 100000000; // still can't make a stack overflow on ubuntu,4GB, phenom
printOff = 1;
int *a;
b = calloc( N, sizeof(int));
a = calloc( N, sizeof(int));
rand_init(a, N);
mergesort(a, N);
printOff = 0;
printArray("LAST", a, N);
free(a);
free(b);
return EXIT_SUCCESS;
}
/* Having failed to translate my concept of non-recursive merge sort,
* I tackled the easier case of recursive merge sort.
* The next task is to translate the recursive version to a non-recursive
* version. This could be done by replacing calls to mergesort, with
* pushes onto a stack of
* tuples of ( <array start address>, <number of elements to process> )
*/
/* The central idea of merging, is that two sorted lists can be
* merged into one sorted list, by comparing the top of each list and
* moving the lowest valued element onto the end of the new list.
* The other list which has the higher valued element keeps its top
* element unchanged. When a list is exhausted, copy the remaining other list
* onto the end of the new list.
*/
/* The recursive part, is to defer any work in sorting an unsorted list,
* by dividing it into two lists until there is only 1 or two elements,
* and if there are two elements, sort them directly by swapping if
* the first element is larger than the second element.
*
* After returning from a recursive call, merge the lists, which will
* begin with one or two element sorted lists. The result is a sorted list
* which will be returned to the parent of the recursive call, and can
* be used for merging.
*/
/* The following is an imaginary discussion about what a programmer
* might be thinking about when programming:
*
* Visualising recursion in terms of a Z80 assembly language, which
* is similar to most assembly languages, there is a data stack (DS) and
* a call stack (CS) pointer, and each recursive call to mergesort
* pushes the return address , which is the program address of the instruction
* after the call , onto the stack pointed to by CS and CS is incremented,
* and the address of the array start and integer which is the subarray length
* onto the data stack pointed to by DS, which will be incremented twice.
*
* If the number of recursive , active calls exceed the allowable space for either the call stack
* or the data stack, then the program will crash , or a process space protection
* violation interrupt signal will be sent by the CPU, and the interrupt vector
* for that signal will jump the processor's current instruction pointer to the
* interrupt handling routine.
*/
- 10, 4, 6, 3, 5, 11 -> 10
- 4, 6, 3, 5, 11 -> 10, 4 : 4 是末尾添加的,不需要交换父节点,因为 4 < 10。
- 6, 3, 5, 11 -> 10, 4, 6 : 6 是末尾添加的,不需要交换父节点,因为 6 < 10。
- 3, 5, 11 -> 10, 4, 6, 3 : 3 是末尾添加的,3 的位置是 4,除以 2 等于 2,4 的位置是 2,不需要交换父节点,因为 4 > 3。
- 5 , 11 -> 10, 4, 6, 3 , 5 : 5 是末尾添加的,5 的位置是 5,除以 2 等于 2,4 的位置是 2,交换父节点,因为 4 < 5; 5 的位置是 2,不需要交换父节点,因为 5 < 10,10 的位置是 1。
- 10 , 5, 6, 3, 4
- 11 -> 10, 5, 6, 3, 4, 11 : 11 是末尾添加的,11 的位置是 6,除以 2 等于 3,交换 6 和 11,11 的位置是 3,交换 11 和 10,停止,因为没有父节点。
- 11, 5, 10, 3, 4, 6
- 11 有子节点 5,10 ; 5 有子节点 3 和 4 ; 10 有子节点 6。父节点总是 > 子节点。
- 11 叶子 * , 5, 10, 3, 4, 6 -> 6 , 5, 10, 3, 4 -> 下沉 -> 选择较大的子节点 5 (2*n+0) 或 10 ( 2*n+1) -> 6 > 10 吗?不 -> 交换 10 和 6 ->
- 10, 5, *6, 3, 4 -> 4 是最大的子节点,因为没有 +1 子节点。6 > 4 吗?是,停止。
- 10 叶子 * , 5 , 6 , 3, 4 -> *4, 5, 6, 3 -> 左 (0) 或右 (+1) 子节点更大 -> +1 更大; 4 > +1 子节点吗?不,交换
- 6,5, *4, 3 -> *4 没有子节点,所以停止。
- 6 叶子 *, 5, 4, 3 -> *3, 5, 4 -> +0 子节点更大 -> 3 > 5 吗?不,所以交换 -> 5, *3, 4 , *3 没有子节点,所以停止。
是
- 5 叶子,所以 3, 4 -> *4, 3 -> +0 子节点最大,因为没有右子节点 -> 4 > 3 吗?不,所以退出
- 4 叶子 3。
- 3 叶子 *.
- 数字按降序提取 11, 10, 6, 5, 4, 3。
一个可能的解决方案,可以是将这个单词排序对快速排序的使用改编为排序整数。否则,一个练习将是为整数重新编写 qsortsimp、partition 和 swap 的非通用 qsort 函数。
/*
* qsortsimp.h
*
* Created on: 17/03/2013
* Author: anonymous
*/
#ifndef QSORTSIMP_H_
#define QSORTSIMP_H_
#include <stdlib.h>
void qsortsimp( void* a, size_t elem_sz, int len, int(*cmp) (void*,void*) );
void shutdown_qsortsimp();
#endif /* QSORTSIMP_H_ */
//----------------------------------------------------------------------------
/* qsortsimp.c
* author : anonymous
*/
#include "qsortsimp.h"
#include<stdlib.h>
#include<string.h>
static void * swap_buf =0;
static int bufsz = 0;
void swap( void* a, int i, int j, size_t elem_sz) {
if (i==j)return;
if (bufsz == 0 || bufsz < elem_sz) {
swap_buf = realloc(swap_buf, elem_sz);
bufsz=elem_sz;
}
memcpy( swap_buf, a+i*elem_sz, elem_sz);
memcpy( a+i*elem_sz, a+j*elem_sz, elem_sz);
memcpy( a+j*elem_sz, swap_buf, elem_sz);
}
void shutdown_qsortsimp() {
if (swap_buf) {
free(swap_buf);
}
}
int partition( void* a, size_t elem_sz, int len, int (*cmp)(void*,void*) ) {
int i = -1;
int j = len-1;
void* v = a + j * elem_sz;
for(;;) {
while( (*cmp)(a + ++i * elem_sz , v ) < 0);
while ( (*cmp)(v, a + --j * elem_sz) < 0 ) if (j==0) break ;
if( i>=j)break;
swap(a, i, j, elem_sz);
}
swap( a, i, len-1, elem_sz);
return i;
}
void qsortsimp( void* a, size_t elem_sz, int len, int(*cmp) (void*,void*) ) {
if ( len > 2) {
int p = partition(a, elem_sz, len, cmp);
qsortsimp( a, elem_sz, p, cmp);
qsortsimp( a+(p+1)*elem_sz, elem_sz, len - p -1, cmp );
}
}
//------------------------------------------------------------------------------
/*
Name : words_quicksort.c
Author : anonymous
Version :
Copyright :
Description : quick sort the words in moby dick in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "qsortsimp.h"
void printArray(const char* a[], int n) {
int i;
for(i=0; i < n; ++i) {
if(i!=0 && i% 5 == 0) {
printf("\n");
}
if (i%1000000 ==0) {
fprintf(stderr,"printed %d words\n", i);
}
printf("%s ", a[i]);
}
printf("\n");
}
const int MAXCHARS=250;
char ** wordlist=0;
int nwords=0;
int remaining_block;
const size_t NWORDS_PER_BLOCK = 1000;
//const char* spaces=" \t\n\r";
//inline isspace(const char ch) {
// int i=0;
// while(spaces[i]!='\0') {
// if(spaces[i++] == ch)
// return 1;
// }
// return 0;
//}
void freeMem() {
int i = nwords;
while(i > 0 ) {
free(wordlist[--i]);
}
free(wordlist);
}
static char * fname="~/Downloads/books/pg2701-moby-dick.txt";
void getWords() {
char buffer[MAXCHARS];
FILE* f = fopen(fname,"r");
int state=0;
int ch;
int i;
while ((ch=fgetc(f))!=EOF) {
if (isalnum(ch) && state==0) {
state=1;
i=0;
buffer[i++]=ch;
} else if (isalnum(ch) && i < MAXCHARS-1) {
buffer[i++]=ch;
} else if (state == 1) {
state =0;
buffer[i++]= '\0';
char* dynbuf = malloc(i);
int j;
for(j=0; j < i; ++j) {
dynbuf[j] = buffer[j];
}
i=0;
if (wordlist == 0 ) {
wordlist = calloc(NWORDS_PER_BLOCK, sizeof(char*));
remaining_block = NWORDS_PER_BLOCK;
} else if ( remaining_block == 0) {
wordlist = realloc(wordlist, (NWORDS_PER_BLOCK + nwords)* sizeof(char*));
remaining_block = NWORDS_PER_BLOCK;
fprintf(stderr,"allocated block %d , nwords = %d\n", remaining_block, nwords);
}
wordlist[nwords++]= dynbuf;
--remaining_block;
}
}
fclose(f);
}
void testPrintArray() {
int i;
for(i=0; i < nwords;++i) {
printf("%s | ", wordlist[i]);
}
putchar('\n');
printf("stored %d words. \n",nwords);
}
int cmp_str_1( void* a, void *b) {
int r = strcasecmp( *((char**)a),*((char**)b));
return r;
}
int main(int argc, char* argv[]) {
if (argc > 1) {
fname = argv[1];
}
getWords();
testPrintArray();
qsortsimp(wordlist, sizeof(char*), nwords, &cmp_str_1);
testPrintArray();
shutdown_qsortsimp();
freeMem();
puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
return EXIT_SUCCESS;
}