查找文件中的最大数
Find largest number in file
我需要在文件中找到最大的整数并打印出来。数字可以超过 100 位,每个数字后面有一个逗号,除了最后一个数字,后面什么都没有。
示例 1:
-87654,-987,-23,-12344
示例 2:
12345123451234512345,678,90,12345123451234512346,12344
这是我的代码:
#include <stdio.h>
int main() {
const char file[] = "numbers.txt";
FILE *fp = fopen(file, "r");
int c = fgetc(fp);
int prev = 0, max = 0, final_max, count = 1, start;
while (c != EOF) {
prev = max;
max = 0;
while (1) {
c = fgetc(fp);
count++;
max++;
if (c == 44 || c == EOF) {
count--;
break;
}
}
if (prev > max) {
final_max = prev;
start = count - final_max;
}
}
fclose(fp);
FILE *fp_fp = fopen(file, "r");
int i = 0;
while (1) {
c = fgetc(fp_fp);
i++;
if (i >= start && i < start + final_max - 1)
printf("%c", c);
if (i == start + final_max)
break;
}
fclose(fp_fp);
return 0;
}
不允许使用数组、字符串和函数fscanf
我的算法如下(变量名在代码中):
- 找出最长数字的位数 (
final_max
)
- 存储没有数组的最长数字的起始索引(
start
)
- 最长数字的最后一个索引是
start + final_max - 1
- 关闭文件并重新打开
- 找到起始索引后,开始一个一个地打印数字,直到到达最后一个索引
我这里有两个问题:
这有时会在数字之前或之后添加额外的数字。
这不适用于负数。
你能帮我修改我的代码以使其正常工作吗?
哪个数字更大?
- 999
- 1000
更长的数字更大。
哪个数字更大?
- 123
- 132
最大最左边位的数字较大。
第二个稍微想一想就知道是对的。只要最左边的数字相同,就可以忽略。因此:
12345 --> 2345 --> 345 --> 45
12372 --> 2372 --> 372 --> 72 --> (7 > 4) therefore (12372 > 12345)
哪个数字更大?
- -7
- 5
正数总是大于负数。
哪个数字更大?
- -123
- -132
两个数字都是负数,这使得答案与两个数字都为正数时的结果相反。换句话说,+123 < +132
因此 -123 > -132
.
让这变得困难的是禁止使用任何类型的数组(字符串)的禁令。我继续假设这包括当前最大的数字。
不幸的是,您当前的代码有点逻辑混乱...
在编写一大堆代码之前,您需要更多地考虑您打算如何解决问题。这里有一些提示:
我们无法存储字符串,但我们可以使用ftell()
和fseek()
跟踪文件中的读取位置。
为了让生活更轻松,我们可以做的其他事情是打开输入文件 两次 — 一次打开当前最大的数字,一次打开当前正在比较的数字。这允许我们为每个文件使用标准 fgetc()
,而不必为两个数字的每个数字来回 fseek()
。
您应该自己编写一个函数来比较两个文件对象中的两个数字:
int compare( FILE * lhs, FILE * rhs );
// returns -1 if lhs < rhs
// returns 0 if lhs == rhs
// returns 1 if lhs > rhs
这个函数真的是最难的部分。在我自己的解决方案中,我发现以下功能也很有帮助:
int fpeek( FILE * f )
{
int c = fgetc( f );
ungetc( c, f );
return c;
}
int sign( FILE * f );
// returns -1 or 1
// if the next character in f is a '-':
// then discard it and return -1 (negative)
// else return 1 (positive)
int next( FILE * f );
// Returns a digit '0'..'9'
// or 0 if end of number (character was a ',' or EOF)
void skip( FILE * f )
// Skip to next number
{
while (next( f )) { }
}
我上面概述的原则是您测试数字所需要的。其中最难的部分是比较 length 和 value。我写了我的
同时做这两件事,但您可能会发现或多或少地做您最初的想法会更容易:
- 比较符号。如果不同你就完成了!
(最大的是non-negative一个)
- 比较长度。如果不同你就完成了!
(如果sign==1最大就是最长,如果sign==-1就是最短)
- 返回并比较值。第一个差异,你就完成了!
如果 sign==1,最大的是第一个较大的值,...
- 没有区别,大功告成:(a==b)!
请记住,符号会翻转 -1
和 1
之间的结果。您可以通过简单的乘法来做到这一点。例如,如果您希望 return lhs
是较大的数字 如果它是正数 那么 return -1 * sign;
.
下一个比较难的部分在main()
,但这至少比比较函数简单。您只需要在循环中找到每个数字的开头并进行比较即可。请记住使用 ftell()
以便能够在调用 compare()
和 skip()
到下一个数字后重置位置。
FILE * f_largest = fopen( "numbers.txt", "r" );
FILE * f_current = fopen( "numbers.txt", "r" );
f_largest
文件对象用于 currently-largest 号码。
f_current
文件对象用于循环比较数字。
这部分算法的工作原理与任何“查找最大数”算法类似:跟踪找到的最大数,直到您查看了所有数字。您看到使用 两个 文件对象如何使这变得简单了吗?
while current is not at EOF:
position of largest = ftell largest
position of current = ftell current
compare largest and current. If current > largest:
largest position = current position
fseek in largest to position of largest
fseek in current to position of current
skip current to next
完成主循环后,您只需在 f_largest
处打印数字。
邪恶的作业!
这些东西旨在真正地锻炼您的大脑。恕我直言,这项特殊作业对于 CS 101 来说有点 over-the-top,但它应该仍然可行。
这些类型的作业确实会随着您的进行而变得更加棘手。重点是让你 努力 直到你能全神贯注地想出一个解决方案。您自己想出的解决方案越多越好。
不过,拥有更多的一般编程经验当然会有所帮助。这个作业假设了一些我认为你还没有真正掌握的跳跃,但我可能对你期望的功能水平有误。
无论如何,希望这次编辑让事情在如何处理这个问题上变得更加清晰。基本点是文件只是字符的另一个来源,就像字符串一样。您只需使用 seek 和 get 函数而不是数组索引来访问它。
那个,你会注意到我(经常)提倡使用小辅助函数。将您的任务分成更小的部分,它变得更易于管理。
不使用数组或字符串的限制有点困难,并且会阻止流处理,因为您必须能够向后查找。
这里是 Dúthomhas 描述的方法的实现。但请注意,它不处理前导零、+
符号或空格:
#include <stdio.h>
int is_digit(int c) { return c >= '0' && c <= '9'; }
int main() {
const char file[] = "numbers.txt";
FILE *fp = fopen(file, "r");
FILE *fp2 = fopen(file, "r");
long largest = 0, current = 0;
int c, c2, cmp = 0, neg = 0, neg2 = 0;
for (;;) {
c = getc(fp);
if (c == '-') {
neg = 1;
c = getc(fp);
}
c2 = getc(fp2);
if (c2 == '-') {
neg2 = 1;
c2 = getc(fp2);
}
if (is_digit(c)) {
if (is_digit(c2)) {
if (cmp == 0)
cmp = c - c2;
continue;
}
/* number is longer than largest */
cmp = 1;
} else
if (is_digit(c2)) {
/* current is shorter */
cmp = -1;
} else {
/* current and largest have the same length */
}
if (neg) {
if (neg2 && cmp < 0)
largest = current;
} else {
if (neg2 || cmp > 0)
largest = current;
}
fseek(fp2, largest, SEEK_SET);
/* skip remaining digits */
while (is_digit(c))
c = getc(fp);
current = ftell(fp);
cmp = neg = neg2 = 0;
if (c == EOF)
break;
}
while ((c = getc(fp2)) != ',' && c != EOF)
putchar(c);
putchar('\n');
fclose(fp);
fclose(fp2);
return 0;
}
我需要在文件中找到最大的整数并打印出来。数字可以超过 100 位,每个数字后面有一个逗号,除了最后一个数字,后面什么都没有。
示例 1:
-87654,-987,-23,-12344
示例 2:
12345123451234512345,678,90,12345123451234512346,12344
这是我的代码:
#include <stdio.h>
int main() {
const char file[] = "numbers.txt";
FILE *fp = fopen(file, "r");
int c = fgetc(fp);
int prev = 0, max = 0, final_max, count = 1, start;
while (c != EOF) {
prev = max;
max = 0;
while (1) {
c = fgetc(fp);
count++;
max++;
if (c == 44 || c == EOF) {
count--;
break;
}
}
if (prev > max) {
final_max = prev;
start = count - final_max;
}
}
fclose(fp);
FILE *fp_fp = fopen(file, "r");
int i = 0;
while (1) {
c = fgetc(fp_fp);
i++;
if (i >= start && i < start + final_max - 1)
printf("%c", c);
if (i == start + final_max)
break;
}
fclose(fp_fp);
return 0;
}
不允许使用数组、字符串和函数fscanf
我的算法如下(变量名在代码中):
- 找出最长数字的位数 (
final_max
) - 存储没有数组的最长数字的起始索引(
start
) - 最长数字的最后一个索引是
start + final_max - 1
- 关闭文件并重新打开
- 找到起始索引后,开始一个一个地打印数字,直到到达最后一个索引
我这里有两个问题:
这有时会在数字之前或之后添加额外的数字。
这不适用于负数。
你能帮我修改我的代码以使其正常工作吗?
哪个数字更大?
- 999
- 1000
更长的数字更大。
哪个数字更大?
- 123
- 132
最大最左边位的数字较大。
第二个稍微想一想就知道是对的。只要最左边的数字相同,就可以忽略。因此:
12345 --> 2345 --> 345 --> 45
12372 --> 2372 --> 372 --> 72 --> (7 > 4) therefore (12372 > 12345)
哪个数字更大?
- -7
- 5
正数总是大于负数。
哪个数字更大?
- -123
- -132
两个数字都是负数,这使得答案与两个数字都为正数时的结果相反。换句话说,+123 < +132
因此 -123 > -132
.
让这变得困难的是禁止使用任何类型的数组(字符串)的禁令。我继续假设这包括当前最大的数字。
不幸的是,您当前的代码有点逻辑混乱...
在编写一大堆代码之前,您需要更多地考虑您打算如何解决问题。这里有一些提示:
我们无法存储字符串,但我们可以使用ftell()
和fseek()
跟踪文件中的读取位置。
为了让生活更轻松,我们可以做的其他事情是打开输入文件 两次 — 一次打开当前最大的数字,一次打开当前正在比较的数字。这允许我们为每个文件使用标准 fgetc()
,而不必为两个数字的每个数字来回 fseek()
。
您应该自己编写一个函数来比较两个文件对象中的两个数字:
int compare( FILE * lhs, FILE * rhs );
// returns -1 if lhs < rhs
// returns 0 if lhs == rhs
// returns 1 if lhs > rhs
这个函数真的是最难的部分。在我自己的解决方案中,我发现以下功能也很有帮助:
int fpeek( FILE * f )
{
int c = fgetc( f );
ungetc( c, f );
return c;
}
int sign( FILE * f );
// returns -1 or 1
// if the next character in f is a '-':
// then discard it and return -1 (negative)
// else return 1 (positive)
int next( FILE * f );
// Returns a digit '0'..'9'
// or 0 if end of number (character was a ',' or EOF)
void skip( FILE * f )
// Skip to next number
{
while (next( f )) { }
}
我上面概述的原则是您测试数字所需要的。其中最难的部分是比较 length 和 value。我写了我的 同时做这两件事,但您可能会发现或多或少地做您最初的想法会更容易:
- 比较符号。如果不同你就完成了!
(最大的是non-negative一个) - 比较长度。如果不同你就完成了!
(如果sign==1最大就是最长,如果sign==-1就是最短) - 返回并比较值。第一个差异,你就完成了!
如果 sign==1,最大的是第一个较大的值,... - 没有区别,大功告成:(a==b)!
请记住,符号会翻转 -1
和 1
之间的结果。您可以通过简单的乘法来做到这一点。例如,如果您希望 return lhs
是较大的数字 如果它是正数 那么 return -1 * sign;
.
下一个比较难的部分在main()
,但这至少比比较函数简单。您只需要在循环中找到每个数字的开头并进行比较即可。请记住使用 ftell()
以便能够在调用 compare()
和 skip()
到下一个数字后重置位置。
FILE * f_largest = fopen( "numbers.txt", "r" );
FILE * f_current = fopen( "numbers.txt", "r" );
f_largest
文件对象用于 currently-largest 号码。
f_current
文件对象用于循环比较数字。
这部分算法的工作原理与任何“查找最大数”算法类似:跟踪找到的最大数,直到您查看了所有数字。您看到使用 两个 文件对象如何使这变得简单了吗?
while current is not at EOF:
position of largest = ftell largest
position of current = ftell current
compare largest and current. If current > largest:
largest position = current position
fseek in largest to position of largest
fseek in current to position of current
skip current to next
完成主循环后,您只需在 f_largest
处打印数字。
邪恶的作业!
这些东西旨在真正地锻炼您的大脑。恕我直言,这项特殊作业对于 CS 101 来说有点 over-the-top,但它应该仍然可行。
这些类型的作业确实会随着您的进行而变得更加棘手。重点是让你 努力 直到你能全神贯注地想出一个解决方案。您自己想出的解决方案越多越好。
不过,拥有更多的一般编程经验当然会有所帮助。这个作业假设了一些我认为你还没有真正掌握的跳跃,但我可能对你期望的功能水平有误。
无论如何,希望这次编辑让事情在如何处理这个问题上变得更加清晰。基本点是文件只是字符的另一个来源,就像字符串一样。您只需使用 seek 和 get 函数而不是数组索引来访问它。
那个,你会注意到我(经常)提倡使用小辅助函数。将您的任务分成更小的部分,它变得更易于管理。
不使用数组或字符串的限制有点困难,并且会阻止流处理,因为您必须能够向后查找。
这里是 Dúthomhas 描述的方法的实现。但请注意,它不处理前导零、+
符号或空格:
#include <stdio.h>
int is_digit(int c) { return c >= '0' && c <= '9'; }
int main() {
const char file[] = "numbers.txt";
FILE *fp = fopen(file, "r");
FILE *fp2 = fopen(file, "r");
long largest = 0, current = 0;
int c, c2, cmp = 0, neg = 0, neg2 = 0;
for (;;) {
c = getc(fp);
if (c == '-') {
neg = 1;
c = getc(fp);
}
c2 = getc(fp2);
if (c2 == '-') {
neg2 = 1;
c2 = getc(fp2);
}
if (is_digit(c)) {
if (is_digit(c2)) {
if (cmp == 0)
cmp = c - c2;
continue;
}
/* number is longer than largest */
cmp = 1;
} else
if (is_digit(c2)) {
/* current is shorter */
cmp = -1;
} else {
/* current and largest have the same length */
}
if (neg) {
if (neg2 && cmp < 0)
largest = current;
} else {
if (neg2 || cmp > 0)
largest = current;
}
fseek(fp2, largest, SEEK_SET);
/* skip remaining digits */
while (is_digit(c))
c = getc(fp);
current = ftell(fp);
cmp = neg = neg2 = 0;
if (c == EOF)
break;
}
while ((c = getc(fp2)) != ',' && c != EOF)
putchar(c);
putchar('\n');
fclose(fp);
fclose(fp2);
return 0;
}