почему printf показывает 0 для размера вектора, когда cout показывает правильный размер?
Вопрос
Я не понимаю, почему я получаю 0, когда использую printf и %d, чтобы получить размер моего вектора:
vector<long long> sieve;
int size;
...
//add stuff to vector
...
size = sieve.size();
printf("printf sieve size: %d \n", size); //prints "printf sieve size: 0"
std::cout << "cout sieve size: ";
std::cout << size;
std::cout << " \n ";
//prints "cout sieve size: 5 (or whatever the correct sieve size is)"
Если я перебираю вектор через
if(i=0;i<sieve.size();i++)
Я получаю правильное количество итераций.
Что я делаю не так или что случилось с printf?size() возвращает целое число, верно??
Вот весь мой небольшой скрипт:
#include <iostream>
#include <vector>
#include <stack>
#include <math.h>
int main (int argc, char * const argv[]) {
unsigned long long answer = 0;
unsigned long long cur = 2;
std::vector<long long> sieve;
unsigned long long limit;
unsigned long long value;
unsigned int i;
int size;
bool isPrime;
std::cout << "Provide a value to find its largest prime factor: ";
std::cin >> value;
limit = ceil(sqrt(value));
sieve.push_back(2);
while(cur++ < limit){
isPrime = true;
sieve.begin();
for(i=0; i<sieve.size();i++){
if(!(cur % sieve[i])){
isPrime = false;
break;
}
}
if(isPrime){
if(!(value % cur)){
std::printf("Is prime factor: %d\n", cur);
sieve.push_back(cur);
answer = sieve[sieve.size() - 1];
size = sieve.size();
std::printf("current last: %d sieve size: %ld\n", answer, size);
for(i=0; i<sieve.size();i++){
std::printf("sieve iter: %d sieve val: %d\n", i, sieve[i]);
std::cout << size;
std::cout << " wtf\n";
}
}
}
}
answer = sieve[sieve.size() - 1];
size = sieve.size();
std::printf("Limit: %d Answer: %d sieve size: %ld\n", limit, answer, size);
return 0;
}
Решение
Теперь, имея полный исходник, всё ясно.
Вы заявили:
int size;
Затем вы использовали:
std::printf("current last: %d sieve size: %ld\n", answer, size);
std::printf("Limit: %d Answer: %d sieve size: %ld\n", limit, answer, size);
Если размер — int, вам следует использовать «%d», а не «%ld».Хороший компилятор предупредил бы вас об этом.GCC выдает следующие предупреждения для вашей исходной версии:
test.cpp: In function ‘int main(int, char* const*)’:
test.cpp:17: warning: converting to ‘long long unsigned int’ from ‘double’
test.cpp:30: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:34: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:34: warning: format ‘%ld’ expects type ‘long int’, but argument 3 has type ‘int’
test.cpp:36: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long long int’
test.cpp:45: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
test.cpp:45: warning: format ‘%d’ expects type ‘int’, but argument 3 has type ‘long long unsigned int’
test.cpp:45: warning: format ‘%ld’ expects type ‘long int’, but argument 4 has type ‘int’
Это говорит о многом.
Вы должны объявить размер как:
std::vector<long long>::size_type size;
Тогда вам следует использовать его как:
std::printf("current last: %llu sieve size: %llu\n", (unsigned long long) answer, (unsigned long long) size);
std::printf("Limit: %llu Answer: %llu sieve size: %llu\n", (unsigned long long) limit, (unsigned long long) answer, (unsigned long long) size);
Конечно, использование iostream позволяет избежать этих проблем, особенно некрасивого приведения в printf() для преобразования размера в тип, известный printf.
Другие советы
Это лажа, потому что у вас есть:
unsigned long long answer = 0;
int size;
и ты звонишь printf
с:
std::printf("current last: %d sieve size: %ld\n", answer, size);
Обе строки формата неверны:
Ты проходишь мимо
answer
кprintf
и форматирование его%d
, но так и должно быть%lld
, поскольку он объявленunsigned long long
.Вы передаете размер с помощью
%d
вместо%ld
.Сsize
есть иint
, должен быть%d
.
Когда эти аргументы передаются в printf, он печатает первые 32 бита. answer
во-первых %d
и вторые 32 бита (или больше, после конца!) answer
для %ld
.Это нет что вы хотите.
Если вы скомпилируете с -Wall
ваш компилятор должен предупредить вас о таких вещах.Обратите особое внимание на предупреждения!
Выглядит безумно.Поскольку размер объявлен как «размер int», printf("...%d") определенно верен.Не может быть, чтобы size_t отличался по размеру от "int", потому что вы явно объявляете "size" как int, а cout << ...размер ...работает правильно.
Вы проверили, что включили?Возможно, без надлежащего объявления в вашей системе printf работает «неправильно».
Ваша проблема в том, что answer
определяется как long long
и вы печатаете его только с помощью %d
.
printf — это функция с переменным числом аргументов, а в C это означает, что компилятор не знает какие аргументы вы передали в функцию.Он не может выполнять обычные преобразования типов, и ему приходится доверять его пользователю, чтобы правильно определить формат аргументов, иначе аргументы не будут правильно извлечены из стека вызовов.
Вы не поняли это правильно.
размеры векторов size_t
, что, как мне кажется, обычно является long
...
Не мог сказать, почему printf
однако не работает.
А size()
метод возвращает size_t
, что зависит от вашей реализации на C++.Когда вы пытаетесь printf("%d")
, вы говорите библиотеке ожидать int
, что не обязательно так;тогда требуется int
из стека вызовов, который принимает только старшие байты size_t
.
Что вам нужно сделать, это принудительно вернуть возвращаемое значение size()
к известному типу данных с приведением:printf("%d", (int) size)
На каком оборудовании вы работаете?Скорее всего, size
это другой тип, чем вы думаете.Распечатать sizeof(size)
и проверьте или попробуйте %ld
.Если у вас машина с прямым порядком байтов, такая как PPC, размер — это long
, и вы печатаете %d
, вы получите конец длинного числа, состоящий из всех нулей.
обновлять
Хорошо, вот что я получаю с Intel Mac mini 10.5:
$ cat trySize.C
#include <iostream>
#include <vector>
int main(){
std::cout << "sizeof(size_t): "
<< sizeof(size_t)
<< std::endl ;
std::vector<long long> sieve ;
std::cout << "sizeof(sieve.size()): "
<< sizeof(sieve.size())
<< std::endl;
printf("sizeof(sieve.size()) (printf): %d\n", sizeof(sieve.size()));
return 0;
}
$ g++ trySize.C
$ ./a.out
sizeof(size_t): 4
sizeof(sieve.size()): 4
sizeof(sieve.size()) (printf): 4
$
Вероятно, вам следует начать разбивать код на более мелкие части и пробовать их;здесь есть что-то странное.
Это будет работать:
std::printf("current last: %**lld** sieve size: %ld\n", answer, size);
Проблема в том, что ответ длинный (64-битное целое число), а %d ожидает 32-битное целое число.Поэтому размер не печатается.Вам нужно будет использовать %lld.
Для получения дополнительной информации о строках формата для printf см.:http://en.wikipedia.org/wiki/Printf